home *** CD-ROM | disk | FTP | other *** search
- /* NOTE: because of size, the previous 'mailbox.c' has been
- * split in 3 parts:
- * mboxcmd.c, containing the 'mbox' subcommands, and
- * mailbox.c, containing some user mailbox commands, and
- * mailbox2.c, containing the remaining user commands.
- * 921125 - WG7J
- */
- /* There are only two functions in this mailbox code that depend on the
- * underlying protocol, namely mbx_getname() and dochat(). All the other
- * functions can hopefully be used without modification on other stream
- * oriented protocols than AX.25 or NET/ROM.
- *
- * SM0RGV 890506, most work done previously by W9NK
- *
- *** Changed 900114 by KA9Q to use newline mapping features in stream socket
- * interface code; everything here uses C eol convention (\n)
- *
- * Numerous new commands and other changes by SM0RGV, 900120
- *
- * Gateway function now support outgoing connects with the user's call
- * with inverted ssid. Users can connect to system alias as well...
- * See also several mods in socket.c,ax25.c and others
- * 11/15/91, WG7J/PA3DIS
- *
- * Userlogging, RM,VM and KM commands, and R:-line interpretation
- * added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
- *
- * Inactivity timeout-disconnect added 920325 and later - WG7J
- *
- * Removed mbox overhead from calling Convers directly from ax25 - KO4KS
- * Several other additions - KO4KS
- */
- #include <stdio.h>
- #include <time.h>
- #include <io.h>
- #include <ctype.h>
- #include <alloc.h>
- #include <stdlib.h>
- #include <string.h>
- #ifdef UNIX
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
- #include <dir.h>
- #include <dos.h>
- #include "global.h"
- #include "config.h"
- #include "timer.h"
- #include "proc.h"
- #include "socket.h"
- #include "usock.h"
- #include "session.h"
- #include "smtp.h"
- #include "dirutil.h"
- #include "telnet.h"
- #include "ftp.h"
- #include "ftpserv.h"
- #include "commands.h"
- #include "netuser.h"
- #include "files.h"
- #include "bm.h"
- #include "pktdrvr.h"
- #include "ax25.h"
- #include "mailbox.h"
- #include "ax25mail.h"
- #include "nr4mail.h"
- #include "cmdparse.h"
- #include "mailfor.h"
- #include "help.h"
- #include "color.h"
-
- #ifdef MAILBOX
-
- /* Log all gateway connects to the logfile - WG7J */
- #define GWTRACE 1
-
- /* By setting the fp to NULL, we can check in exitbbs()
- * wether a tempfile has been closed or not - WG7J
- */
- #define MYFCLOSE(x) { fclose(x); x = (FILE *) 0; }
-
- /*
- #define MBDEBUG
- */
-
- extern char *Mbhaddress;
- extern time_t StartTime;
- extern char Myalias[];
- extern int Mbfullsvc;
- extern char stars[];
- #ifdef TIPMAIL
- extern long Mbtipperms;
- #endif
- #ifdef WPAGES
- extern int MbWpages;
- #endif
- extern int Mbconverse;
- extern int FWDlzw;
- extern int MbLogging;
- extern int Smtpheaders;
-
- struct mbx *Mbox[NUMMBX];
- int BbsUsers = 0;
- int Totallogins, Conflogins, Tutorlogins[3], BBSlogins;
- extern char *MMotd;
- extern char *MExit;
- extern char *Mtmsg;
- /* extern unsigned Maxlet; */
- extern int BBSdump;
- extern short SecureTelnet;
-
- int MbSent = 0;
- int MbRead = 0;
- int MbRecvd = 0;
- #ifdef MBFWD
- int MbForwarded = 0;
- #endif
- static long lastsentid = 0;
-
- extern char Noperm[];
- extern char Nosock[];
- extern char MboxId[], MboxIdFwd[];
- extern char *ANSIArea, *ANSILogin;
-
- #ifdef ITT
- static char DFAR Loginbanner[] = "\n%s (%s)\n\n";
- #else
- static char DFAR Loginbanner[] = "\nKA9Q NOS - %s (%s)\n\n";
- #endif
- static char DFAR RLoginbanner[] = "\nRemote Login at %s - %s\n\n";
-
- char DFAR Howtoend[] = "End with /EX or ^Z in first column (^A aborts):\n";
- static char DFAR CcLine[] = "Cc: ";
- static char DFAR Mbwelcome[] = "\nWelcome %s, ";
- static char DFAR Mbbanner[] = "to the %s TCP/IP Mailbox (%s)\n";
- static char DFAR Mbwarning[] = "Third Party mail is not permitted.\n";
- char DFAR CurUsers[] = "There are currently %d users on the BBS\n";
- char DFAR Only[] = "You are the only user currently on the BBS\n";
- static char DFAR MessageData[] = "%4d message%s - %4d new.\n";
- static char DFAR SMessageData[] = "%4d message%s - %4d new. (%4d on hold)\n";
- char DFAR MsgAborted[] = "*** Message aborted\n";
- static char DFAR sendthemail[] = "Send this message (N=no)?";
-
- static char DFAR Mbmenu[] = "Current msg# %-d of %-d.\n?,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z ";
-
- extern char Mbnrid[];
-
- #ifdef nope
- #ifdef NETROM
- #ifdef CALLCLI
- static char Longmenu[] = "(?)help (A)rea (B)ye (C)onnect (D)ownload (E)scape\n"
- "(F)inger (H)elp (I)nfo (J)heard (K)ill (L)ist (M)boxusers\n"
- "(N)odes (O)perator (P)orts (Q)uery (R)ead (S)end (T)elnet\n"
- "(U)pload (V)erbose (W)hat (X)pert (Z)ap\n";
- #else
- static char Longmenu[] = "(?)help (A)rea (B)ye (C)onnect (D)ownload (E)scape (F)inger\n"
- "(H)elp (I)nfo (J)heard (K)ill (L)ist (M)boxusers (N)odes\n"
- "(O)perator (P)orts (R)ead (S)end (T)elnet (U)pload\n"
- "(V)erbose (W)hat (X)pert (Z)ap\n";
- #endif /*CALLCLI*/
- #else /*NETROM*/
- #ifdef CALLCLI
- static char DFAR Longmenu[] = "(?)help (A)rea (B)ye (C)onnect (CONF)erence (D)ownload (E)scape (F)inger\n"
- "(H)elp (I)nfo (J)heard (K)ill (L)ist (M)boxusers (O)perator (P)orts\n"
- "(Q)uery (R)ead (S)end (T)elnet (U)pload (V)erbose (W)hat (X)pert\n"
- "(Z)ap\n\n"
- "For further help, type 'help cmdname', where 'cmdname' is one of the above.\n\n";
- #else
- static char DFAR Longmenu[] = "(?)help (A)rea (B)ye (C)onnect (CONF)erence (D)ownload (E)scape (F)inger\n"
- "(H)elp (I)nfo (J)heard (K)ill (L)ist (M)boxusers (O)perator (P)orts\n"
- "(R)ead (S)end (T)elnet (U)pload (V)erbose (W)hat (X)pert (Z)ap\n\n"
- "For further help, type 'help cmdname', where 'cmdname' is one of the above.\n\n";
- #endif /*CALLCLI*/
- #endif /*NETROM*/
- #endif /* nope */
-
- extern int isgroup __ARGS((char *group));
- extern char *mblookname __ARGS((struct mbx *m,char *str));
- extern int dombusers __ARGS((int argc,char *argv[],void *p));
- extern int dombpast __ARGS((int argc,char *argv[],void *p));
- static int doarea __ARGS((int argc,char *argv[],void *p));
- extern int dombstatus __ARGS((int argc,char *argv[],void *p));
- static int dombcallbook __ARGS((int argc,char *argv[],void *p));
- void quickscan __ARGS((struct mbx *m, int olduser));
- extern void netPrompt __ARGS((void));
- extern int CountConfUsers __ARGS((void));
- extern char *getquote __ARGS((void));
- extern void tutorserv __ARGS((char *call, struct mbx *m, int mode, int color, int ip));
- extern char *skipwhite __ARGS((char *ptr));
- extern char *skipnonwhite __ARGS((char *ptr));
- extern void askhome __ARGS((struct mbx *m,int initial));
- extern int dosysop __ARGS((int argc,char *argv[],void *p));
- #ifdef LZW
- void togglelzw __ARGS((int soc, int mode));
- #endif
- extern char *cmd_line __ARGS((int argc,char *argv[],char stype));
- extern char *nntp_name_expansion __ARGS((char *name));
-
- #ifdef WPAGES
- void wpageAdd __ARGS((char *entry, int bbs, int updateit));
- #endif
- extern char *host_or_wpage_exp __ARGS((char *to,int hier,int exphome));
- extern char *wpage_exp __ARGS((char *to,int hier,int exphome));
- extern FILE *subdir_fopen __ARGS((char *name, char *mode));
-
- extern int Usenrid;
- extern int MBSecure;
- extern int Mbsendquery;
- #ifdef MBXTDISC
- extern int32 Mbtdiscinit;
- #endif
-
- /*Enlighten them a bit!
- */
- static void
- dombconnecthelp() {
- #ifdef NETROM
- tputs("Syntax: 'C <node>' for NET/ROM connects\n");
- #endif /* NETROM */
- tputs("Syntax: 'C <port> <call>' for AX.25 connects\n\n");
- }
-
- void
- bbscolorcls(m)
- struct mbx *m;
- {
- if (m->usecolor)
- colorcls ();
- }
-
- void
- bbscolorchange (m, str)
- struct mbx *m;
- unsigned char *str;
- {
- if (m->usecolor)
- colorchange (str, m->colorset);
- }
-
-
- int
- dombports(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp;
- struct mbx *m = (struct mbx *)p;
- tputs("Available ports:\n");
- for(ifp=Ifaces;ifp!=NULLIF;ifp=ifp->next)
- if(ifp->type == CL_AX25 && \
- (!(ifp->flags & HIDE_PORT) || (m->privs & SYSOP_CMD)) ) {
- tprintf("%-7s",ifp->name);
- if(ifp->descr != NULLCHAR)
- tprintf(": %s",ifp->descr);
- else
- tputc('\n');
- }
- tputc('\n');
- return 0;
- }
-
- /* This is called by the finger-daemon */
- void
- listusers(s)
- int s;
- {
- int outsave;
- struct mbx m;
-
- m.privs = 0;
- m.stype = ' ';
-
- #ifdef notdef
- usprintf(s,"\nCurrent remote users:\n");
- #endif
- outsave = Curproc->output;
- Curproc->output = s;
- dombusers(0,NULLCHARP,&m);
- Curproc->output = outsave;
- }
-
- struct mbx *
- newmbx()
- {
- int i;
- struct mbx *m;
-
- for(i = 0; i < NUMMBX; i++){
- if(Mbox[i] == NULLMBX){
- m = Mbox[i] = (struct mbx *)callocw(1,sizeof(struct mbx));
- m->mbnum = i;
- BbsUsers++;
- return m;
- }
- }
- /* If we get here, there are no free mailbox sessions */
- return NULLMBX;
- }
-
- static int
- mbx_getname(m)
- struct mbx *m;
- {
- char *cp;
- FILE *tfp;
- union sp sp;
- char tmp[MAXSOCKSIZE];
- int len = MAXSOCKSIZE;
- int anony = 0;
- int oldmode;
- int founddigit=0;
- int count=0;
-
- sp.p = tmp;
- sp.sa->sa_family = AF_LOCAL; /* default to AF_LOCAL */
- getpeername(m->user,tmp,&len);
- m->family = sp.sa->sa_family;
- m->path = mallocw(MBXLINE);
- /* This is one of the two parts of the mbox code that depends on the
- * underlying protocol. We have to figure out the name of the
- * calling station. This is only practical when AX.25 or NET/ROM is
- * used. Telnet users have to identify themselves by a login procedure.
- */
- switch(sp.sa->sa_family){
- #ifdef AX25
- case AF_NETROM:
- case AF_AX25:
- /* NETROM and AX25 socket address structures are "compatible" */
- /*Save user call, in case she/he wants to use gateway function*/
- memcpy(m->call,sp.ax->ax25_addr,AXALEN);
- m->call[ALEN] &= 0xfc;/*Make sure E-bit isn't set !*/
- pax25(m->name,sp.ax->ax25_addr);
- cp = strchr(m->name,'-');
- if(cp != NULLCHAR) /* get rid of SSID */
- *cp = '\0';
- /* SMTP wants the name to be in lower case */
- strlwr (m->name);
- anony = 1;
- /* Try to find the privileges of this user from the userfile */
- if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony)) == -1){
- m->privs = 0;
- free(m->path);
- m->path = NULLCHAR;
- }
- if(m->privs & EXCLUDED_CMD)
- return -1;
- return 0;
- #endif
- case AF_LOCAL:
- case AF_INET:
- m->state = MBX_LOGIN;
- if (m->type == RLOGIN_LINK)
- tprintf(RLoginbanner,Hostname,Version);
- else {
- tprintf(Loginbanner,Version,Hostname);
- if(Mtmsg != NULLCHAR)
- tputs(Mtmsg);
- }
- for(;;){
- /* Maximum of 3 tries - WG7J */
- if(count++ == 3)
- return -1;
- oldmode = sockmode(m->user,SOCK_ASCII);
- tputs("login: ");
- usflush(m->user);
- if(mbxrecvline(m) == -1)
- return -1;
- if(*m->line == 4) /* Control-d */
- return -1;
- if(*m->line == '\0')
- continue;
-
- /* add a little test to avoid 'Mailfile busy' syndrome - WG7J */
- if((cp=strchr(m->line,'.')) != NULLCHAR)
- *cp = '_';
- if((cp=strchr(m->line,'/')) != NULLCHAR)
- *cp = '_';
- if((cp=strchr(m->line,'\\')) != NULLCHAR)
- *cp = '_';
- if((tfp=fopen(m->line,"w")) == NULL) /* Invalid name */
- continue;
- fclose(tfp);
- unlink(m->line);
- if(strlen(m->line) < sizeof(m->name))
- strcpy(m->name,m->line);
- else /* Too long! */
- continue;
- tprintf("Password: %c%c%c",IAC,WILL,TN_ECHO);
- usflush(m->user);
- sockmode(m->user,SOCK_BINARY);
- if(mbxrecvline(m) == -1)
- return -1;
- tprintf("%c%c%c",IAC,WONT,TN_ECHO);
- sockmode(m->user,oldmode);
- tputc('\n');
- usflush(m->user);
- /* This is needed if the password was send before the
- * telnet no-echo options were receied. We neeed to
- * flush the eold sequence from the input buffers, sigh
- */
- if(socklen(m->user,0))/* discard any remaining input */
- recv_mbuf(m->user,NULL,0,NULLCHAR,0);
- if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony))
- != -1){
- if(anony)
- log(m->user,"MBOX login: %s Password: %s",m->name,m->line);
- else
- log(m->user,"MBOX login: %s",m->name);
- if(m->privs & EXCLUDED_CMD)
- return -1;
- #ifdef TIPMAIL
- if (anony && m->type == TIP)
- m->privs = Mbtipperms;
- #endif
- #ifdef AX25
- /*try to set the name as the user-call.
- *this is a very crude test! Be careful...
- *Login must have at least 1 digit (0-9) in it,
- *and it must be possible to convert it to a call.
- *if this doesn't work, disallow the gateway command,
- *no matter if this was allowed by priviledges or not.
- *Be careful, some one with login name '4us' and
- *permission set to allow gateway/netrom, will
- *go out as '4us-15' or '4us-0' !!!!!
- *11/15/91 WG7J/PA3DIS
- */
- for(cp=m->name;*cp != '\0';cp++)
- if(isdigit((int)*cp))
- break;
- if(*cp != '\0')
- founddigit = 1;
- if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
- m->privs &= ~AX25_CMD;
- m->privs &= ~NETROM_CMD;
- }
- #else
- m->privs &= ~AX25_CMD;
- m->privs &= ~NETROM_CMD;
-
- #endif /* AX25 */
- /* Set the morerows to MAXLIN for telnet logins - WG7J */
- m->morerows = MAXLIN - 1;
- return 0;
- }
- tputs("Login incorrect\n");
- log(m->user,"MBOX login FAILED - login: %s Password: %s",m->name,m->line);
- mail_error("MBOX Login failed: %s, pw %s",m->name,m->line);
- *m->name = '\0'; /* wipe any garbage */
- }
- }
- return 0;
- }
-
- /* put up the prompt */
- void
- putprompt(m)
- struct mbx *m;
- {
- char area[64];
- char *cp1,*cp2;
- int inconf;
-
- if(m->sid & MBX_SID)
- tputs(">\n");
- else {
- bbscolorchange (m, "09");
- if(m->sid & MBX_NRID)
- tputs(Mbnrid);
- if(m->sid & MBX_AREA) {
- cp1 = m->area;
- cp2 = area;
- /* Convert / and \ into . */
- while(*cp1 != '\0') {
- if(*cp1=='/')
- *cp2 = '.';
- else
- *cp2 = *cp1;
- cp1++;
- cp2++;
- }
- *cp2 = '\0';
- tprintf("Area: ");
- bbscolorchange (m, "0C");
- tprintf ("'%s' ", area);
- bbscolorchange (m, "09");
- if(m->privs & SYSOP_CMD) {
- #ifdef CONVERS
- inconf = CountConfUsers ();
- #else
- inconf = 0;
- #endif
- if((BbsUsers > 1) || inconf) {
- tputs ("(");
- if (BbsUsers > 1) {
- bbscolorchange (m, "0F");
- tprintf("%-d", BbsUsers);
- bbscolorchange (m, "09");
- tprintf(" users");
- }
- #ifdef CONVERS
- if ((BbsUsers > 1) && inconf)
- tputs (", ");
- if (inconf) {
- bbscolorchange (m, "0F");
- tprintf ("%-d", inconf);
- bbscolorchange (m, "09");
- tprintf (" in conference");
- }
- #endif
- tputs (") ");
- }
- }
- }
- bbscolorchange (m, "0B");
- tprintf((m->sid & MBX_EXPERT) ? (m->sid & MBX_AREA) ? "(%-d/%-d)" : "" : Mbmenu, m->current, m->nmsgs);
- bbscolorchange (m, "0A");
- tprintf (">\n");
- bbscolorchange (m, "0E");
- }
- }
-
- #ifdef MBXTDISC
- /* Mailbox user has been idle for too long,
- * disconnect the socket - WG7J
- */
- void
- mboxredundant(m)
- struct mbx *m;
- {
- struct usock *up;
-
- #ifdef notdef
- /* After fix from Mark, ve3dte this is not needed anymore - WG7J */
- /* nasty hack! we may have screwed up reference count */
- /* by invoking newproc("smtp_send",....); Fudge it! */
- if((up = itop(m->user)) != NULLUSOCK)
- up->refcnt = 1;
- #endif
-
- /* exitbbs (m); */
- /* Close the socket*/
- close_s(m->user);
- return; /* Keep lint happy */
- }
- #endif
-
- extern void mbox_converse __ARGS((int, char *, int, struct mbx *));
-
- /* Incoming mailbox session */
- void
- mbx_incom(s,t,p)
- int s;
- void *t;
- void *p;
- {
- struct tipcb *tip;
- struct mbx *m;
- struct usock *up;
- char *buf[3], *cp;
- char tmp[AXBUF];
- int rval;
- time_t newuser, loguser();
-
- sockmode(s,SOCK_ASCII);
- sockowner(s,Curproc); /* We own it now */
- /* Secede from the parent's sockets, and use the network socket that
- * was passed to us for both input and output. The reference
- * count on this socket will still be 1; this allows the domboxbye()
- * command to work by closing that socket with a single call.
- * If we return, the socket will be closed automatically.
- */
- close_s(Curproc->output);
- close_s(Curproc->input);
- Curproc->output = Curproc->input = s;
-
- /* We'll do our own flushing right before we read input */
- setflush(s,-1);
-
- if((m = newmbx()) == NULLMBX) {
- tputs("Too many mailbox sessions\n");
- return;
- }
-
- m->user = s;
- m->escape = 20; /* default escape character is Ctrl-T */
- m->type = (int) t;
- m->colorset[0] = 0;
- #ifdef TIPMAIL
- #ifdef XMODEM
- if (m->type==TIP) {
- tip = (struct tipcb *) p;
- tip->raw=0;
- m->tip=tip;
- }
- #endif
- #endif
-
- /* ??? */
- while(socklen(s,0)) /* discard any remaining input */
- recv_mbuf(s,NULL,0,NULLCHAR,0);
-
-
- /* get the name of the remote station */
- if(mbx_getname(m) == -1) {
- exitbbs(m);
- return;
- }
- Totallogins++;
- newuser = loguser(m);
-
- #ifdef RLOGINSERV
- if ((int)t == RLOGIN_LINK) {
- tputc ('\n');
- dosysop (1, (char **)0, (void *)m);
- exitbbs(m);
- return;
- }
- #endif
- #ifdef CONVERS
- if((int)t != TIP && (int)t & CONF_LINK) {
- if(m->privs & NO_CONVERS)
- tputs(Noperm);
- else {
- m->state = MBX_CONVERS;
- chname(Curproc,"conference");
- log(s,"open CONF");
- {
- int fd = m->user;
- char name[20];
- strcpy (name, m->name);
- Mbox[m->mbnum] = NULLMBX;
- free((char *)m);
- BbsUsers--;
- mbox_converse (fd, name, (int) -1, NULLMBX);
- }
- }
- close_s(Curproc->output);
- return;
- }
- #endif
-
- #ifdef TUTOR
- if((int)t != TIP && ((int)t & TUTOR_LINK || (int)t & INFO_LINK || (int)t & NEWS_LINK)) {
- m->state = MBX_TUTOR;
- chname(Curproc,"tutorial");
- log(s,"open TUTORIAL");
- {
- char name[20];
- strcpy (name, m->name);
- Mbox[m->mbnum] = NULLMBX;
- free((char *)m);
- BbsUsers--;
- /* setflush(s,'\n'); */ /* automatic flushing each line */
- tutorserv (name, NULLMBX, ((int)t & INFO_LINK) ? 1 : ((int)t & NEWS_LINK) ? 2 : 0, m->usecolor, 0);
- sleep (2);
- }
- close_s(Curproc->output);
- return;
- }
- #endif
-
- log(s,"open MBOX for '%s'", m->name);
-
- if (MbLogging) {
- char buf[128];
- FILE *out;
- sprintf(buf,"%s/mbox.log",Spool);
- if((out = fopen(buf,APPEND_TEXT)) != NULLFILE) {
- time_t t;
- time(&t);
- fprintf (out, "MBOX from %s %s on %s", m->name, m->realname, ptime(&t));
- fclose (out);
- }
- }
-
- BBSlogins++;
- #ifdef MBXTDISC
- /*Start inactivity timer - WG7J */
- set_timer(&m->tdisc,Mbtdiscinit * 1000L);
- m->tdisc.func = mboxredundant;
- m->tdisc.arg = m;
- start_timer(&m->tdisc);
- #endif
- if(m->privs & IS_BBS)
- /* m->sid = MBX_SID; */ /*force bbs status*/
- m->sid = MBX_EXPERT; /* make BBS 'SID' itself, else it's sysop enters as EXPERT */
- else if(m->privs & IS_EXPERT)
- m->sid |= MBX_EXPERT;
-
- /* newuser = loguser(m); */
- #ifdef LZW
- if (m->sid & MBX_TNOS) {
- tputs ("Use LZW Compression (*y/n) ?\n");
- if (mbxrecvline(m) != -1) {
- if (tolower (*m->line) != 'n')
- togglelzw (m->user, 1);
- }
- }
- #endif
- m->state = MBX_CMD; /* start in command state */
- if (!(m->privs & IS_BBS) && (m->sid & MBX_GFX))
- colorfile (ANSILogin, m->colorset);
-
- tputs(FWDlzw ? MboxIdFwd : MboxId);
-
- /* Say 'hello' only if user is not a bbs - WG7J */
- /* if(!(m->sid & MBX_SID)) { */
- if(!(m->privs & IS_BBS)) {
- bbscolorchange (m, "0F");
- if (m->home[0] == '-')
- askhome (m, 1);
- if (m->realname == NULLCHAR)
- askrealname (m, 1);
- if(!(m->sid & MBX_RDMOTD)) {
- DisplayFile (MOTDfile, s);
- m->sid |= MBX_RDMOTD;
- m->update = 1;
- }
- if (m->privs & SYSOP_CMD)
- DisplayFile (MOTDsysfile, s);
- tprintf(Mbwelcome,m->name);
- #ifdef AX25
- if(m->family == AF_INET)
- #endif
- tprintf(Mbbanner,Hostname,Version);
- #ifdef AX25
- else
- tprintf(Mbbanner,pax25(tmp,Mycall),Version);
- #endif
- if (newuser > 0)
- tprintf ("Last on the BBS: %s", ctime(&newuser));
- if (BbsUsers == 1)
- tprintf (Only);
- else
- tprintf(CurUsers,BbsUsers);
- if(!ThirdParty || !Mbfullsvc)
- tputs(Mbwarning);
- if (!newuser)
- DisplayFile (NEWUSERfile, s);
- tflush ();
- #ifdef USERLOG
- if (m->sid & MBX_STATS)
- quickscan (m, (int) newuser);
- #endif
- cp = getquote();
- if (cp) {
- tprintf ("\nQuote of the Day:");
- bbscolorchange (m, "0A");
- tprintf ("\n%s", cp);
- bbscolorchange (m, "0F");
- }
- if(((!cp) || strcmp (MMotd, cp)) && MMotd != NULLCHAR)
- tprintf ("\n%s", MMotd);
- free (cp);
- usflush(m->user);
- #ifdef oldway
- /* Enable our local message area,
- * only if we're not a bbs - WG7J
- */
- buf[1] = m->name;
- doarea(2,buf,m);
- } else
- m->mysize = 0;
- #else
- m->special = ' ';
- }
- /* Enable our local message area */
- buf[1] = m->name;
- doarea(2,buf,m);
- #endif
-
- /* Send prompt */
- if(!(m->privs & IS_BBS))
- putprompt(m);
- else /* first prompt to a BBS has color disabled, after this it
- depends on whether we have seen an SID. If an SID, no color.
- This allows the BBS's SYSOP to 'live' login and have color
- capabilities (after the first prompt). */
- tputs(">\n");
-
- while(mbxrecvline(m) != -1) {
- if (m->privs & EXCLUDED_CMD)
- break;
- if(m->special) /* no-color BBS first prompt, also */
- bbscolorchange (m, "0F");
- if((rval = mbx_parse(m)) == -2)
- break;
- if(rval == 2)
- break;
- if (rval && BBSdump && (m->sid & MBX_SID))
- break;
- if (m->privs & EXCLUDED_CMD)
- break;
- if(rval == 1)
- tputs("Bad syntax.\n");
- notifynewmail (m);
- /* Do not check mailfile if we're bbs, saves a tmpfile- WG7J*/
- if(!(m->sid & MBX_SID))
- scanmail(m);
- putprompt(m);
- m->state = MBX_CMD;
- }
- exitbbs(m);
-
- #ifdef notdef
- /* After fix from Mark, ve3dte this is not needed anymore - WG7J */
- /* by invoking newproc("smtp_send",....); Fudge it! */
- if((up = itop(Curproc->output)) != NULLUSOCK)
- up->refcnt = 1;
- #endif
- usflush(Curproc->output);
- mspause(500L);
- close_s(Curproc->output);
- }
-
- void
- exitbbs(m)
- struct mbx *m;
- {
- #ifdef MBXTDISC
- stop_timer(&m->tdisc);
- #endif
- closenotes(m);
- free(m->to);
- free(m->tofrom);
- free(m->origto);
- free(m->origbbs);
- free(m->subject);
- free(m->date);
- free(m->tomsgid);
- free(m->path);
- free(m->home);
- /* Close the tempfiles if they are not nullpointers - WG7J */
- if(m->tfile != (FILE *) 0)
- fclose(m->tfile);
- if(m->tfp != (FILE *) 0)
- fclose(m->tfp);
- if(m->stdinbuf != NULLCHAR)
- free(m->stdinbuf);
- if(m->stdoutbuf != NULLCHAR)
- free(m->stdoutbuf);
- free((char *)m->mbox);
- Mbox[m->mbnum] = NULLMBX;
- free((char *)m);
- if (BbsUsers)
- BbsUsers--;
- log(Curproc->output,"close MBOX from '%s'", m->name);
- }
-
- /**********************************************************************/
-
- int dochat __ARGS((int argc,char *argv[],void *p));
- static int dombconnect __ARGS((int argc,char *argv[],void *p));
- int dombconvers __ARGS((int argc,char *argv[],void *p));
- static int dombcall __ARGS((int argc,char *argv[],void *p));
- int dodownload __ARGS((int argc,char *argv[],void *p));
- int dombupload __ARGS((int argc,char *argv[],void *p));
- int dowhat __ARGS((int argc,char *argv[],void *p));
- int dozap __ARGS((int argc,char *argv[],void *p));
- int dosend __ARGS((int argc,char *argv[],void *p));
- static int dosid __ARGS((int argc,char *argv[],void *p));
- int dosysop __ARGS((int argc,char *argv[],void *p));
- int dostars __ARGS((int argc,char *argv[],void *p));
- int dombhelp __ARGS((int argc,char *argv[],void *p));
- int dombtelnet __ARGS((int argc,char *argv[],void *p));
- int dombfinger __ARGS((int argc,char *argv[],void *p));
- int dombquote __ARGS((int argc,char *argv[],void *p));
- int dombtutor __ARGS((int argc,char *argv[],void *p));
- int dombnews __ARGS((int argc,char *argv[],void *p));
- int dombexpert __ARGS((int argc,char *argv[],void *p));
- int dobump __ARGS((int argc,char *argv[],void *p));
- int dombfdesc __ARGS((int argc,char *argv[],void *p));
- int dombtime __ARGS((int argc,char *argv[],void *p));
- int dombwpages __ARGS((int argc,char *argv[],void *p));
- int dombset __ARGS((int argc,char *argv[],void *p));
- int dombget __ARGS((int argc,char *argv[],void *p));
- int dombrmail __ARGS((int argc,char *argv[],void *p));
- int dombgroup __ARGS((int argc,char *argv[],void *p));
- int doreply __ARGS((int argc,char *argv[],void *p));
- int douser __ARGS((int argc,char *argv[],void *p));
- int dombexpand __ARGS((int argc,char *argv[],void *p));
- int dombslip __ARGS((int argc,char *argv[],void *p));
- int dombjheard __ARGS((int argc,char *argv[],void *p));
- int dombiproute __ARGS((int argc,char *argv[],void *p));
- int dombroute __ARGS((int argc,char *argv[],void *p));
- extern int dobbshome __ARGS((int argc,char *argv[],void *p));
- static void gw_alarm __ARGS((void *p));
- static void gw_input __ARGS((int s,void *notused,void *p));
- static void gw_superv __ARGS((int null,void *proc,void *p));
- static int mbx_to __ARGS((int argc,char *argv[],void *p));
- int mbx_data __ARGS((struct mbx *m,struct list *cclist,char *extra, int returnreceipt));
- int msgidcheck __ARGS((char *string));
- static int thirdparty __ARGS((struct mbx *m));
- extern int doipheard __ARGS((int argc,char *argv[],void *p));
- extern int dorealname __ARGS((int argc,char *argv[],void *p));
- extern int doversion __ARGS((int argc,char *argv[],void *p));
- #ifdef NETROM
- static int dombnrnodes __ARGS((int argc,char *argv[],void *p));
- extern int donrneighbour __ARGS((int argc,char *argv[],void *p));
- #endif
-
- struct cmds DFAR Mbcmds[] = {
- "", doreadnext, 0, 0, NULLCHAR,
- "?", dombhelp, 0, 0, NULLCHAR,
- "Area", doarea, 0, 0, NULLCHAR,
- "Bye", domboxbye, 0, 0, NULLCHAR,
- "BUmp", dobump, 0, 0, NULLCHAR,
- "Connect", dombconnect, 0, 0, NULLCHAR,
- #ifdef CALLBOOK
- "CAll", dombcall, 0, 0, NULLCHAR,
- #endif
- #ifdef SAMCALLB
- "CAll", dombcallbook, 0, 2, "Call callsign\nMultiple callsigns allowed per line",
- #endif
- #ifdef CONVERS
- "CONFerence", dombconvers, 0, 0, NULLCHAR,
- #endif
- #ifdef XMODEM
- "Download", dodownload, 0, 2, "D[U|X] filename",
- #else
- "Download", dodownload, 0, 2, "D[U] filename",
- #endif
- /* next entry out of order DELIBERATELY, to make "D" download, not del! */
- "DEl", dozap, 0, 2, "DEL filename",
- "DIr", dowhat, 0, 0, NULLCHAR,
- "Escape", dombescape, 0, 0, NULLCHAR,
- "EXit", domboxbye, 0, 0, NULLCHAR,
- "EXPand", dombexpand, 0, 2, "EXPand aliasname",
- "Finger", dombfinger, 0, 0, NULLCHAR,
- /* next entry out of order DELIBERATELY, to make "F" finger, not fdesc! */
- "FDesc", dombfdesc, 0, 2, "FD filename",
- "Get", dombget, 0, 0, NULLCHAR,
- "GRoup", dombgroup, 0, 2, "GROUP action groupname",
- "Help", dombhelp, 0, 0, NULLCHAR,
- "HOme", dobbshome, 0, 0, NULLCHAR,
- "Info", dombhelp, 0, 0, NULLCHAR,
- /* next entry out of order DELIBERATELY, to make "I" info, not iheard! */
- "IHeard", doipheard, 0, 0, NULLCHAR,
- "IProute", dombiproute, 0, 0, NULLCHAR,
- #ifdef AX25
- "Jheard", dombjheard, 0, 0, NULLCHAR,
- #endif
- "Kill", dodelmsg, 0, 0, NULLCHAR,
- "List", dolistnotes, 0, 0, NULLCHAR,
- "Mboxusers", dombusers, 0, 0, NULLCHAR,
- "Name", dorealname, 0, 0, NULLCHAR,
- #ifdef TUTOR
- "NEws", dombnews, 0, 0, NULLCHAR,
- #endif
- #ifdef NETROM
- "NOdes", dombnrnodes, 0, 0, NULLCHAR,
- "NRoutes", donrneighbour, 0, 0, NULLCHAR,
- #endif
- "Operator", dochat, 0, 0, NULLCHAR,
- "Ping", doping, 0, 0, NULLCHAR,
- "POrts", dombports, 0, 0, NULLCHAR,
- "Quit", domboxbye, 0, 0, NULLCHAR,
- /* next entry out of order DELIBERATELY, to make "Q" quit, not query! */
- #if defined(CALLCLI) || defined(SAMCALLB)
- "QUEry", dombcallbook, 0, 2, "Q callsign\nMultiple callsigns allowed per line",
- #endif
- "QUOte", dombquote, 0, 0, NULLCHAR,
- "Read", doreadmsg, 0, 0, NULLCHAR,
- "REPly", doreply, 0, 0, NULLCHAR,
- #ifdef RMAIL
- "RMAil", dombrmail, 0, 2, "RMAIL destbbs",
- #endif
- "ROute", dombroute, 0, 2, "ROute address",
- "Send", dosend, 0, 0, NULLCHAR,
- "SET", dombset, 0, 2, "SET A|C|F|M|N|S|SI|X",
- #ifdef TIPMAIL
- "SLip", dombslip, 0, 0, NULLCHAR,
- #endif
- "Telnet", dombtelnet, 0, 2, "T hostname",
- "TIme", dombtime, 0, 0, NULLCHAR,
- #ifdef TUTOR
- "TUtor", dombtutor, 0, 0, NULLCHAR,
- #endif
- #ifdef XMODEM
- "Upload", dombupload, 0, 2, "U[X] filename",
- #else
- "Upload", dombupload, 0, 2, "U filename",
- #endif
- "USer", douser, 0, 0, NULLCHAR,
- "Verbose", doreadmsg, 0, 0, NULLCHAR,
- "VERSion", doversion, 0, 0, NULLCHAR,
- "What", dowhat, 0, 0, NULLCHAR,
- #ifdef WPAGES
- "WPages", dombwpages, 0, 2, "WP call [@bbs]",
- #endif
- "Xpert", dombexpert, 0, 0, NULLCHAR,
- "Zap", dozap, 0, 2, "Z filename",
- /* the rest aren't displayed with "?" */
- "[", dosid, 0, 0, NULLCHAR,
- "@", dosysop, 0, 0, NULLCHAR,
- #ifdef AX25
- #ifdef MBFWD
- "f>", dorevfwd, 0, 0, NULLCHAR,
- #endif
- #endif
- "***", dostars, 0, 0, NULLCHAR,
- NULLCHAR, NULLFP, 0, 0, "Huh?",
- };
-
- /* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
- * They have to be treated specially since cmdparse() wants a space between
- * the actual command and its arguments.
- * "SP FOO" is converted to "s foo" and the second command letter is saved
- * in m->stype. Longer commands like "SEND" are unaffected, except for
- * commands starting with "[", i.e. the SID, since we don't know what it will
- * look like.
- */
- static char twocmds[] = "aslrd[mvkxwiu"; /* A,S,L,R,D,M,V,K,X,W,I,U are two-letter commands */
-
- int
- mbx_parse(m)
- struct mbx *m;
- {
- char *cp, *cp2;
- int i;
- char *newargv[2];
- unsigned char specialfound = 0;
- int inbid = 0, sendtype = 0;
-
- /* Skip any spaces at the begining */
- for(cp = m->line;isspace(*cp);++cp)
- ;
- if (tolower (*cp) == 's')
- sendtype = 1; /* a 'send' command, of some form */
-
- /* Translate entire buffer to lower case */
- /* fix by KO4KS to convert a message's BID to upper case. */
- for (cp2 = cp; *cp2 != '\0'; ++cp2) {
- if (sendtype && !inbid && *cp2 == '$')
- inbid = 1;
- if (!inbid)
- *cp2 = tolower(*cp2);
- else
- *cp2 = toupper(*cp2);
- if (*cp2 == ' ')
- inbid = 0;
- }
-
- m->special = m->stype = ' ';
- if (*cp == '^' || *cp == '~') {
- if (cp[1] == 's') {
- m->special = *cp;
- specialfound = 0x80;
- }
- *cp++ = ' ';
- }
- if(*cp != '\0' && *(cp+1) != '\0')
- for(i=0; i<strlen(twocmds); ++i) {
- if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
- || *cp == '[')) {
- if(islower(*(++cp)))
- m->stype = toupper(*cp); /* Save the second character */
- else
- m->stype = *cp;
- m->stype |= specialfound;
- *cp = ' ';
- break;
- }
- }
- /* See if the input line consists solely of digits */
- cp = m->line;
- for(cp = m->line;isspace(*cp);++cp)
- ;
- if (*cp == ';')
- return 0; /* allow self-identification */
- newargv[1] = cp;
- for(;*cp != '\0' && isdigit(*cp);++cp)
- ;
- if(*cp == '\0' && strlen(newargv[1]) > 0) {
- newargv[0] = "r";
- return doreadmsg(2,newargv,(void *)m);
- }
- return cmdparse(Mbcmds,m->line,(void *)m);
- }
-
- /* This works like recvline(), but telnet options are answered and the
- * terminating newline character is not put into the buffer. If the
- * incoming character equals the value of escape, any queued input is
- * flushed and -2 returned.
- */
- int
- mbxrecvline(m)
- struct mbx *m;
- {
- int s = m->user;
- int escape = m->escape;
- char *buf = m->line;
- int c, cnt = 0, opt;
-
- if(buf == NULLCHAR)
- return 0;
- usflush(Curproc->output);
- #ifdef MBXTDISC
- start_timer(&m->tdisc);
- #endif
- while((c = recvchar(s)) != EOF){
- if(!m->inmessage && c == IAC){ /* Telnet command escape */
- if((c = recvchar(s)) == EOF)
- break;
- if(c > 250 && c < 255 && (opt = recvchar(s)) != EOF){
- #ifdef foo
- switch(c){
- case WILL:
- tprintf("%c%c%c",IAC,DONT,opt);
- break;
- case WONT:
- tprintf("%c%c%c",IAC,DONT,opt);
- break;
- case DO:
- tprintf("%c%c%c",IAC,WONT,opt);
- break;
- case DONT:
- tprintf("%c%c%c",IAC,WONT,opt);
- }
- #endif
- /* to be fixed usflush(Curproc->output);*/
- continue;
- }
- if(c != IAC && (c = recvchar(s)) == EOF)
- break;
- }
- /* ordinary character */
- #ifndef TNOS_68K
- if(c == '\r' || c == '\n')
- #else
- if(c == '\r' || c == '\l')
- #endif
- break;
- if(!m->inmessage && uchar(c) == escape){
- if(socklen(s,0)) /* discard any remaining input */
- recv_mbuf(s,NULL,0,NULLCHAR,0);
- cnt = -2;
- break;
- }
- /* Handle <del> chars - from wa7tas */
- if(!m->inmessage && c == 8) {
- if(cnt > 0) {
- *--buf = 0;
- cnt--;
- }
- } else {
- *buf++ = c;
- ++cnt;
- }
- if(cnt == (MBXLINE - 1)) {
- cnt = -2;
- break;
- }
- }
- if(c == EOF && cnt == 0)
- return -1;
- *buf = '\0';
- #ifdef MBXTDISC
- /* Restart the timeout-timer - WG7J*/
- start_timer(&m->tdisc);
- #endif
- return cnt;
- }
-
- extern void updatedefaults __ARGS((struct mbx *, int));
-
- int
- domboxbye(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
- long elapsedtime;
- char *cptr;
-
- m = (struct mbx *)p;
-
- #ifdef USERLOG
- if(!(m->sid & MBX_SID)) /* not a BBS */
- setlastread(m);
- if(m->update)
- updatedefaults(m, 0);
- #endif
- if(m->sid & MBX_SID) { /* if a BBS */
- smtptick (NULL); /* clean up any unfiled mail */
- mspause (500L);
- return -2; /* for bbs's, just disconnect */
- }
-
- /* Now say goodbye */
- bbscolorchange (m, "09");
- tprintf("\nThank you ");
- bbscolorchange (m, "0C");
- tprintf (m->name);
- bbscolorchange (m, "09");
- #ifdef ITT
- tprintf (", for calling the %s TMNG Tcp/Ip Mailbox.\n", Hostname);
- #else
- tprintf (", for calling the %s TNOS Tcp/Ip Mailbox.\n", Hostname);
- #endif
- time((time_t *)&elapsedtime);
- cptr = ctime((time_t *) &elapsedtime);
- rip (cptr);
- elapsedtime -= m->logontime;
- tprintf ("Logged off: ");
- bbscolorchange (m, "0F");
- tprintf (cptr);
- bbscolorchange (m, "09");
- tprintf (" --- Time this session: ");
- bbscolorchange (m, "0F");
- tprintf ("%s\n", tformat (elapsedtime));
- if(MExit != NULLCHAR)
- tprintf("%s\n",MExit);
- #ifdef nope ALLSERV
- if(m->type == TIP)
- tputs("Please hang up now.\n");
- #endif
- /* usflush(m->user); */
- usflush(Curproc->output);
- return -2; /* signal that exitbbs() should be called */
- }
-
- char *
- addroot (root,name)
- char *root, *name;
- {
- return strdup (make_fname (root, name));
- }
-
-
- char *
- permtest (path, privs, name, mode, root, dir)
- char *path, *name, *root;
- long privs;
- int mode, dir;
- {
- char *file, *defdir, *cp;
-
- if (root == NULLCHAR) {
- defdir = strdup(path);
- if ((cp = strchr (defdir, ';')) != NULLCHAR)
- *cp = 0;
- } else defdir = strdup (root);
- if (dir)
- file = strdup(defdir);
- else
- file = addroot (defdir, name);
- free (defdir);
- if(!permcheck(path,privs,mode,file)) {
- free (file);
- tputs(Noperm);
- return 0;
- }
- return file;
- }
-
-
- #if defined(CALLBOOK)
- extern char *InetCallserver;
- extern char *InetCallserverport;
-
- /*This is a simple way of estiblishing a connection
- *to a callbook-server via tcp - WG7J
- */
- static int
- dombcall(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char buf[8], *newargv[3];
-
- if(InetCallserver!=NULLCHAR){
- newargv[0] = "C";
- newargv[1] = InetCallserver;
- newargv[2] = InetCallserverport;
- SecureTelnet = 0;
- return dombtelnet(3,newargv,p);
- }
- else {
- tputs("Internet callserver not configured\n");
- }
- /* It returns only after a disconnect or refusal */
- return 0;
- }
-
- #endif /*CALLBOOK*/
-
- #if defined(CALLCLI) || defined(SAMCALLB)
- static int
- dombcallbook(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
- char buf[8], *newargv[3];
- extern char *Callserver;
- int req, ret = 0;
-
- if(argc > 2){
- tputs("Usage: Q callsign [callsign] [...]\n");
- return -1;
- }
- m = (struct mbx *) p;
- #ifndef newcode
- sprintf(buf,"%d",IPPORT_CALLDB);
- newargv[0] = "C";
- #else /* to call KF5MG's callbook server, through FINGER */
- sprintf(buf,"%d",IPPORT_FINGER);
- newargv[0] = "t";
- #endif
- newargv[1] = Callserver;
- newargv[2] = buf;
-
- for (req = 1; req < argc; req++) {
- if (argv[req] == NULLCHAR) return ret;
- log(m->user, "%s checking callbook: %s",m->name,argv[req]);
- if (!Callserver || !*Callserver) {
- #ifdef SAMCALLB
- cb_lookup (Curproc->output, argv[req], (FILE *) 0);
- #else
- cb_lookup (Curproc->output, argv[req]);
- #endif
- ret = 0;
- } else {
- m->startmsg = mallocw(80); /* is freed each time by gw_connect() */
- sprintf(m->startmsg,"%s\n", argv[req]);
- tprintf("Looking for \"%s\" in the callbook at %s\n",argv[req],Callserver);
- SecureTelnet = 0;
- ret = dombtelnet(3,newargv,p);
- }
- }
- return ret; /* It looks like all possible returns are zero anyway! */
- }
- #endif
-
-
- extern int Mbloophold;
-
- /*Some additional security - WG7J
- *NO_3PARTY = disallow all 3rd party mail
- *NO_SENDCMD = only allow mail to sysop
- */
- extern int NoBid;
-
- int
- dosend(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int cccnt = 0, fail = 0;
- char *host, *cp, *rhdr = NULLCHAR;
- struct list *ap, *cclist = NULLLIST;
- struct mbx *m;
- FILE *fp;
- time_t now;
- int done = 0;
- char *cp2;
- char returnreceipt = 0, nosig = 0;
- int foundCTLz = 0;
- int c;
- long here, datastart;
-
- #ifdef RLINE
- struct tm t;
- #define ODLEN 16
- #define OBLEN 32
- char origdate[ODLEN];
- char origbbs[OBLEN];
- char fwdbbs[NUMFWDBBS][FWDBBSLEN+1];
- int myfwds = 0;
- register int i;
- int zulu;
- int check_r = 0, check_r2 = 0;
- int found_r = 0, wrotedata = 0;
- int loops = 0;
- char Me[15];
- int recvsize;
- long messagesize;
-
- origdate[0] = '\0';
- origbbs[0] = '\0';
- #endif
-
- m = (struct mbx *)p;
- if (m->stype & 0x80) {
- if (m->special == '~')
- nosig = 1;
- else
- returnreceipt = 1;
- m->stype &= 0x7f;
- }
-
- #ifdef TIPMAIL
- if(m->stype == 'L')
- return (dombslip (argc, argv, p));
- #endif
- if((m->stype != 'R' || (m->sid & MBX_SID)) && mbx_to(argc,argv,m) == -1) {
- tputs((m->sid & MBX_SID) ? "NO - syntax error\n" : \
- "S command syntax error - format is:\nS[C|F] name [@ host] [< from_addr] [$bulletin_id]\nSR [number]\n");
- mail_error("%s: MBOX S syntax error - %s\n",m->name,cmd_line(argc,argv,m->stype));
- return 0;
- }
-
- bbscolorchange (m, "0D");
-
- /*Check for send permission */
- if(m->privs & NO_SENDCMD) { /*is this to 'SYSOP' or 'sysop' ?*/
- if(stricmp(m->to,"sysop")) {
- tputs((m->sid & MBX_SID) ? "NO - permission denied\n" : \
- "Sorry, only mail to 'sysop' allowed!\n");
- mail_error("%s: no mail permission - %s\n",m->name,m->to);
- return 0;
- }
- }
-
- /* Check for a BID on bulletins from other bbs's - WG7J */
- if((m->sid & MBX_SID) && !NoBid &&
- (m->stype == 'B') && (m->tomsgid == NULLCHAR)) {
- tputs("NO - No BID!\n");
- log(m->user,"MBOX %s: SB without BID - %s",m->name,m->to);
- mail_error("MBOX %s: SB without BID - %s",m->name,m->to);
- return 0;
- }
-
- pwait (NULL); /* just to be nice to others */
- if(m->stype != 'R' && msgidcheck(m->tomsgid)) {
- if(m->sid & MBX_SID)
- tputs("NO - ");
- tprintf("Already have %s\n",m->tomsgid);
- return 0;
- }
-
- pwait (NULL); /* just to be nice to others */
- /* if (!(m->sid & MBX_SID)) */ /* if BBS, no need! */
- if ((m->stype != 'B') && (m->stype != 'T') && (m->stype != 'R'))
- m->to = host_or_wpage_exp (m->to, 1, 0);
-
-
- #ifdef WPAGES
- check_r2 = 1;
- #endif
- if(m->stype == 'R' && !(m->sid & MBX_SID))
- if (mbx_reply(argc,argv,m,&cclist,&rhdr) == -1)
- return 0;
- else
- check_r2 = 0;
- if((cp = rewrite_address(m->to)) != NULLCHAR)
- if(stricmp(m->to,cp) != 0) {
- m->origto = m->to;
- m->to = cp;
- } else
- free(cp);
-
- pwait (NULL); /* just to be nice to others */
- /* refuse any mail that gets rewritten into 'refuse' - WG7J */
- if(!stricmp(m->to,"refuse")) {
- tputs((m->sid & MBX_SID) ? "NO - refused\n" : \
- "Bad user or hostname, please mail 'sysop' for help\n");
- free (rhdr);
- return 0;
- }
-
- if( ((!Mbfullsvc || !ThirdParty) && !(m->privs & SYSOP_CMD)) || (m->privs & NO_3PARTY) )
- if(thirdparty(m) == 0) {
- if (m->sid & MBX_SID)
- tputs ("NO - ");
- tputs(Mbwarning);
- mail_error("%s: 3rd party mail refused - %s\n",m->name,m->to);
- free (rhdr);
- return 0;
- }
-
- /* Send the new 'To:' line to sysops only - WG7J */
- if((m->privs&SYSOP_CMD) && (m->origto != NULLCHAR || m->stype == 'R') && !(m->sid & MBX_SID))
- tprintf("To: %s\n", m->to);
- if(validate_address(m->to) == 0) {
- tputs((m->sid & MBX_SID) ? "NO - bad address\n" : \
- "Bad user or hostname, please mail 'sysop' for help\n");
- free(rhdr);
- del_list(cclist);
- /* We don't free any more buffers here. They are freed upon
- * the next call to mbx_to() or to domboxbye() */
- return 0;
- }
- pwait (NULL); /* just to be nice to others */
- /* Display the Cc: line (during SR command) */
- for(ap = cclist; ap != NULLLIST; ap = ap->next) {
- if(cccnt == 0){
- tprintf("%s",Hdrs[CC]);
- cccnt = 4;
- } else {
- tputs(", ");
- cccnt += 2;
- }
- if(cccnt + strlen(ap->val) > 80 - 3) {
- tputs("\n ");
- cccnt = 4;
- }
- tputs(ap->val);
- cccnt += strlen(ap->val);
- }
- if(cccnt)
- tputc('\n');
-
- pwait (NULL); /* just to be nice to others */
- /* If the the command was 'SC' then read the Cc: list now - WG7J */
- if((m->stype == 'C') && !(m->sid & MBX_SID)) {
- m->stype = 'P'; /* make everything private */
- tputs(CcLine);
- if(mbxrecvline(m) != -1) {
- if(strlen(m->line)) {
- if(*m->line == 0x01) { /* CTRL-A, abort */
- free(rhdr);
- del_list(cclist);
- tputs(MsgAborted);
- return 0;
- }
- cp = m->line;
- /* get all the Cc addresses, separated by comma's */
- while((cp2=strchr(cp,',')) != NULLCHAR) {
- *cp2 = '\0';
- /*get rid of leading spaces or tabs*/
- while(*cp == ' ' || *cp == '\t')
- cp++;
- if(strlen(cp)) {
- cp = host_or_wpage_exp (strdup (cp), 0, 0);
- addlist(&cclist,cp,0,cp);
- free (cp);
- }
- cp = cp2 + 1;
- }
- /* Do the last or only one */
- /* get rid of leading spaces or tabs*/
- while(*cp == ' ' || *cp == '\t')
- cp++;
- if(strlen(cp)) {
- cp = host_or_wpage_exp (strdup (cp), 0, 0);
- addlist(&cclist,cp,0,cp);
- free (cp);
- }
- }
- } else {
- free(rhdr);
- del_list(cclist);
- return 0;
- }
- }
-
- /* Now check to make sure we can create the needed tempfiles - WG7J */
- if((m->tfile = tmpfile()) == NULLFILE) {
- free(rhdr);
- del_list(cclist);
- tputs((m->sid & MBX_SID) ? "NO - no temp file\n" : \
- "Can't create temp file for mail\n");
- return -2; /* disconnect if no files!! */
- }
- #ifdef RLINE
- pwait (NULL); /* just to be nice to others */
- /* Only accept R: lines from bbs's */
- if((m->sid & MBX_SID)&&(Rdate || Rreturn || Rfwdcheck || Mbloophold)){
- /* Going to interpret R:headers, we need another tempfile ! */
- if((m->tfp = tmpfile()) == NULLFILE) {
- free(rhdr);
- del_list(cclist);
- tputs("NO - no temp file\n");
- return 0;
- }
- /* Now we got enough :-) */
- check_r = 1;
- Checklock++;
- /* Set the call, used in loop detect code - WG7J */
- if(Mbloophold) {
- pax25(Me,Mycall);
- if((cp = strchr(Me,'-')) != NULLCHAR)
- *cp = '\0'; /* remove SSID */
- }
- }
- #endif
-
- m->state = MBX_SUBJ;
- pwait (NULL); /* just to be nice to others */
- if(m->stype != 'R' || (m->sid & MBX_SID)) {
- tputs((m->sid & MBX_SID) ? "OK\n" : "Subject:\n");
- if(mbxrecvline(m) == -1) {
- #ifdef RLINE
- if(check_r) {
- MYFCLOSE(m->tfp);
- Checklock--;
- }
- #endif
- free (rhdr);
- return 0;
- }
- } else /* Replying to a message */
- tprintf("Subject: %s\n",m->line);
-
- m->subject = strdup(m->line);
-
- #ifdef RLINE
- if(!check_r) {
- #endif
- mbx_data(m,cclist,rhdr, returnreceipt);
- wrotedata = 1;
- #ifdef RLINE
- }
- #endif
- free(rhdr);
- m->state = MBX_DATA;
- pwait (NULL); /* just to be nice to others */
-
- #ifdef RMAIL
- if (m->change == -1) {
- /* Write RMAIL line */
- fseek (m->tfile, -2, 1);
- for(ap = cclist; ap != NULLLIST; ap = ap->next) {
- #if 0
- if(cccnt == 0) {
- fprintf(m->tfile,"%s",Hdrs[TO]);
- cccnt = 4;
- cp2 = (m->origto) ? m->origto : m->to;
- cp = strchr (cp2, '.');
- i = (cp) ? (int)(cp - cp2) : strlen (cp2);
- fwrite (cp2, 1, i, m->tfile);
- cccnt += i;
- }
- #endif
- fprintf(m->tfile,", ");
- cccnt += 2;
- fputs(ap->val,m->tfile);
- cccnt += strlen(ap->val);
- if (cccnt > 508)
- break;
- }
- if(cccnt)
- fputs("\n\n",m->tfile);
- del_list(cclist);
- cclist = NULLLIST;
- }
- pwait (NULL); /* just to be nice to others */
- #endif
-
- if(!(m->sid & MBX_SID)) {
- if((m->privs&SYSOP_CMD) && (m->origto != NULLCHAR || m->stype == 'R') && !strcmp(m->to, "check"))
- tprintf("\007The system doesn't know where to route this message..\nSuggest you abort this message and re-enter!\n");
- tprintf("Enter %smessage%s%s",(m->stype == 'F') ? "a personal " : "",
- (m->stype == 'F') ? " to precede the forwarded message.\n" : ". ", Howtoend);
- }
-
- bbscolorchange (m, "07");
- #if 0 /* now in mbx_data() */
- /* Add a return receipt line, if requested */
- if (returnreceipt) {
- fseek (m->tfile, -1, 1);
- fprintf(m->tfile, "%s%s@%s\n\n", Hdrs[RRECEIPT],m->name,Hostname);
- returnreceipt = 0;
- }
- #endif
- datastart = ftell (m->tfile);
- m->inmessage = 1;
- if(Rfwdcheck) { /* checking sender here JUST IN CASE R: line is bad or missing */
- for(i=0;i<Numfwds;i++) {
- if(!stricmp(MyFwds[i],m->name)) {
- /*Found it !*/
- strcpy(fwdbbs[myfwds++],m->name);
- break;
- }
- }
- }
- while(!foundCTLz && ((recvsize = mbxrecvline(m)) != -1)) {
- pwait (NULL); /* just in case sender is hosing us */
- if ((cp = strchr (m->line, CTLZ)) != NULLCHAR) {
- *(cp+1) = 0;
- *cp = '\n';
- foundCTLz = 1;
- }
- if(m->line[0] == 0x01 || !strnicmp(m->line, "/a", 2)) { /* CTRL-A */
- MYFCLOSE(m->tfile);
- #ifdef RLINE
- if(check_r)
- MYFCLOSE(m->tfp);
- #endif
- tputs(MsgAborted);
- del_list(cclist);
- return 0;
- }
- if(m->line[0] != CTLZ && strnicmp(m->line, "/e", 2) && strnicmp(m->line, "/b", 2) && strnicmp (m->line, "/q", 2) && strcmp (m->line, ".")) {
- if (*m->line == '/' && !(m->sid & MBX_SID)) {
- cp = &m->line[2];
- cp = skipnonwhite (cp);
- cp = skipwhite (cp);
- c = i = 0;
- switch (tolower (m->line[1])) {
- case 'o': i = 1;
- case 'v': if (m->stype != 'R')
- break;
- if ((fp = tmpfile ()) != NULLFILE) {
- tprintf ("%sOriginal message #%-d\n", stars, m->current);
- msgtofile(m, m->current, fp, i);
- rewind (fp);
- sendfile(fp, m->user, ASCII_TYPE,0);
- tprintf ("%s\n", stars);
- fclose (fp);
- }
- break;
- case 'f': if (!(cp = permtest(m->path, m->privs,cp,RETR_CMD, NULLCHAR, 0)))
- break;
- if((fp = fopen(cp,READ_TEXT)) != NULLFILE) {
- tprintf ("%sAdded file: %s\n", stars, cp);
- while(fgets(m->line,LINELEN,fp) != NULLCHAR)
- fputs(m->line,m->tfile);
- fclose(fp);
- }
- free (cp);
- break;
- case 'd': if (*cp)
- i = atoi (cp);
- if (!i)
- i = 1;
- tprintf ("%sDeleted %d line%s\n", stars, i, (i - 1) ? "s" : "");
- here = ftell (m->tfile);
- while (here > 0) {
- fseek (m->tfile, --here, SEEK_SET);
- if ((fgetc (m->tfile)) == '\n' && !(i--))
- break;
- fseek (m->tfile, here, SEEK_SET);
- putc ('\0', m->tfile);
- }
- break;
- case '/': strcpy (m->line, &m->line[1]);
- c = 1;
- break;
- case 's': nosig ^= 1;
- tprintf ("%sSignature o%s\n", stars, nosig ? "ff" : "n");
- break;
- case 'p': here = ftell (m->tfile);
- fseek (m->tfile, datastart, SEEK_SET);
- sendfile(m->tfile,m->user,ASCII_TYPE,0);
- fseek (m->tfile, here, SEEK_SET);
- tprintf ("%s\n", stars);
- break;
- case 'c': if(strlen(cp)) {
- cp = host_or_wpage_exp (strdup (cp), 0, 0);
- addlist(&cclist,cp,0,cp);
- tprintf ("%sAdded call: %s\n", stars, cp);
- free (cp);
- }
- break;
- case 'm': i = atoi (cp);
- if (i && i <= m->nmsgs) {
- msgtofile(m,i,m->tfile,0);
- tprintf ("%sAdded Message: %d\n", stars, i);
- }
- break;
- case 'h':
- case '?': bbscolorchange (m, "0B");
- DisplayFile (EditorHelp, m->user);
- bbscolorchange (m, "07");
- break;
- }
- if (!c)
- continue;
- }
-
- #ifdef RLINE
- if(check_r || check_r2) {
- pwait (NULL); /* just to be nice to others */
- /* Check for R: lines to start with */
- /* Invalidate R: lines that don't have R:YYMMDD/ */
- if((!strnicmp(m->line,"R:",2)) && (*(m->line+8) == '/')) { /* found one */
- found_r = 1;
- /*Write this line to the second tempfile
- *for later rewriting to the real one */
- fprintf(m->tfp,"%s\n",m->line);
- /* Find the '@[:]CALL.STATE.COUNTRY'or
- * or the '?[:]CALL.STATE.COUNTRY' string
- * The : is optional. */
- if( ((cp=strchr(m->line,'@')) != NULLCHAR) || ((cp=strchr(m->line,'?')) != NULLCHAR) ) {
- if((cp2=strpbrk(cp," \n\t")) != NULLCHAR)
- *cp2 = '\0';
- /* Some bbs's send @bbs instead of @:bbs*/
- if (*++cp == ':')
- cp++;
- #ifdef nope /* was WPAGES, now done in smtpserv */
- if(MbWpages)
- wpageAdd (cp, 1, 1);
- #endif
- pwait (NULL); /* just to be nice to others */
- /* if we use 'return addres' copy whole 'domain' name */
- if(Rreturn)
- if((strlen(cp) <= OBLEN) && (strlen(cp)))
- strcpy(origbbs,cp);
- /* Optimize forwarding ? */
- if(Rfwdcheck || Mbloophold) {
- /*if there is a HADDRESS, cut off after '.'*/
- if((cp2=strchr(cp,'.')) != NULLCHAR)
- *cp2 = '\0';
- if(Mbloophold)
- /* check to see if this is my call ! */
- if(!stricmp(Me,cp))
- loops++;
- /*cross-check with MyFwds list*/
- if(Rfwdcheck) {
- for(i=0;i<Numfwds;i++) {
- if(!stricmp(MyFwds[i],cp)) {
- /*Found one !*/
- strcpy(fwdbbs[myfwds++],cp);
- break;
- }
- }
- }
- }
- }
- if(Rdate) {
- /* Find the 'R:yymmdd/hhmmz' string */
- if((cp=strchr(m->line,' ')) != NULLCHAR) {
- *cp = '\0';
- if(strlen(m->line+2) <= ODLEN)
- strcpy(origdate,m->line+2);
- }
- }
- } else { /* if not R: line */
- /* The previous line was last R: line
- * so we're done checking
- * now write the smtp headers and
- * all saved R: lines to the right tempfile */
- if (check_r) {
- check_r = 0;
- Checklock--;
- if (Checklock < 0)
- Checklock = 0;
- }
- check_r2 = 0;
- /*Did we actually find one ?*/
- if(found_r) {
- if(Rreturn)
- m->origbbs = strdup(strlwr(origbbs));
- if(Rdate) {
- if((cp=strchr(origdate,'/')) != NULLCHAR) {
- if((*(cp+5) == 'z') || (*(cp+5) == 'Z')) {
- *(cp+5) = '\0';
- zulu = 1;
- }
- t.tm_min = atoi(cp+3);
- *(cp+3) = '\0';
- t.tm_hour = atoi(cp+1);
- *cp = '\0';
- t.tm_mday = atoi(&origdate[4]);
- origdate[4] = '\0';
- t.tm_mon = (atoi(&origdate[2]) - 1);
- origdate[2] = '\0';
- t.tm_year = atoi(origdate);
- /* Set the date in rfc 822 format */
- m->date = mallocw(40);
- sprintf(m->date,"%.2d %s %02d %02d:%02d:00 %.3s\n",
- t.tm_mday, Months[t.tm_mon], t.tm_year, t.tm_hour, t.tm_min, zulu ? "UTC" : "");
- }
- }
- }
- /* Now write the headers,
- * possibly adding Xforwarded lines for bulletins,
- * or anything that has a BID.
- * Add the X-Forwarded lines FIRST,
- * this speeds up forwarding... */
- if(Mbloophold && loops >= Mbloophold)
- fprintf(m->tfile,"%sLoop\n",Hdrs[XBBSHOLD]);
- if(Rfwdcheck && found_r && ((m->stype == 'B') || (m->tomsgid)) ) {
- /*write Xforwarded headers*/
- for(i=0;i<myfwds;i++)
- fprintf(m->tfile,"%s%s\n",Hdrs[XFORWARD],fwdbbs[i]);
- }
- /*write regular headers*/
- if (!wrotedata) {
- mbx_data(m,cclist,NULLCHAR, returnreceipt);
- wrotedata = 1;
- }
- pwait (NULL); /* just to be nice to others */
-
- /* Now copy the R: lines back */
- if(found_r) {
- char tmpline[MBXLINE];
- rewind(m->tfp);
- while(fgets(tmpline,sizeof(tmpline),m->tfp)!=NULLCHAR) {
- pwait (NULL); /* just to be nice to others */
- fputs(tmpline,m->tfile);
- }
- }
- MYFCLOSE(m->tfp);
- /* And add this first non-R: line */
- fprintf(m->tfile,"%s\n",m->line);
- }
- } else { /* not check_r or check_r2 */
- #endif
- fprintf(m->tfile,"%s",m->line);
- if (recvsize != - 2)
- putc ('\n', m->tfile);
- }
- } else { /* CTLZ or /ex */
- #ifdef RLINE
- if(check_r) {
- /* Hmm, this means we never finished the R: headers
- * tmp file still open ! */
- MYFCLOSE(m->tfp);
- }
- #endif
- done = 1; /* To indicate the difference between
- * mbxrecvline() returning -1 and /ex ! - WG7J
- * Now also used to indicate if the message should
- * be sent or not ! */
- /* Now ask users if they want to send this ! - WG7J */
- if( Mbsendquery && !(m->sid & MBX_SID)) {
- if(m->type == TELNET || m->type == TIP)
- c = tkeywait(sendthemail,0);
- else /* For AX.25 and NET/ROM connects */
- c = mykeywait(sendthemail,m);
- if(c == -1 || c == 'n' || c == 'N') {
- done = 0; /* signal delete of message */
- tputs(MsgAborted);
- }
- }
- break; /* all done */
- }
- }
- if(!done && !foundCTLz) {
- /* We did NOT get ^Z or /EX, but mbxrecvline returned -1 !!!
- * This means the connection is gone ! - WG7J */
- MYFCLOSE(m->tfile);
- #ifdef RLINE
- if(check_r)
- MYFCLOSE(m->tfp);
- #endif
- del_list(cclist);
- /* free(rhdr); */ /*Just in case*/
- return 0;
- }
- m->inmessage = 0;
- if (m->stype == 'F') { /* type == 'F' */
- tputs ("Inserting original message...\n");
- usflush(m->user);
- fprintf(m->tfile,"----- Forwarded message -----\n\n");
- msgtofile(m,m->current,m->tfile,0);
- fprintf(m->tfile,"----- End of forwarded message -----\n");
- }
-
- /* Insert customized signature if one is found */
- if(!nosig && !(m->sid & MBX_SID)) { /* not a forwarding BBS */
- char sigwork[LINELEN];
- sprintf(sigwork,"%s/%s.sig",Signature,m->tofrom ? m->tofrom : m->name);
- if((fp = fopen(sigwork,READ_TEXT)) != NULLFILE) {
- while(fgets(sigwork,LINELEN,fp) != NULLCHAR) {
- pwait (NULL); /* just to be nice to others */
- fputs(sigwork,m->tfile);
- }
- fclose(fp);
- }
- }
-
- if((host = strrchr(m->to,'@')) == NULLCHAR) {
- host = Hostname; /* use our hostname */
- if(m->origto != NULLCHAR) {
- /* rewrite_address() will be called again by our
- * SMTP server, so revert to the original address.
- */
- free(m->to);
- m->to = m->origto;
- m->origto = NULLCHAR;
- }
- } else
- host++; /* use the host part of address */
-
- {
- char fullfrom[MBXLINE];
-
- /* make up full from name for work file */
- if(m->tofrom != NULLCHAR)
- sprintf(fullfrom,"%s%%%s@%s",m->tofrom, m->name, Hostname);
- else
- sprintf(fullfrom,"%s@%s",m->name,Hostname);
- if(cclist != NULLLIST && stricmp(host,Hostname) != 0) {
- fseek(m->tfile,0L,0); /* reset to beginning */
- pwait (NULL); /* just to be nice to others */
- fail = queuejob(m->tfile,Hostname,cclist,fullfrom);
- del_list(cclist);
- cclist = NULLLIST;
- }
- addlist(&cclist,m->to,0,m->to);
- fseek(m->tfile,0L,0);
- pwait (NULL); /* just to be nice to others */
- fail += queuejob(m->tfile,host,cclist,fullfrom);
- }
- del_list(cclist);
- messagesize = filelength (fileno(m->tfile));
- MYFCLOSE(m->tfile);
- if(fail) {
- if(!(m->sid & MBX_SID)) /* only when we're not a bbs */
- tputs("Couldn't queue message for delivery\n");
- } else {
- if(!(m->sid & MBX_SID)) /* only when we're not a bbs */
- tputs("Message queued\n");
- if(m->sid & MBX_SID)
- MbRecvd++;
- else {
- MbSent++;
- if (MbHolding && m->stype == 'B')
- tputs("Bulletins are held till reviewed by the SYSOP\n");
- }
- #ifdef notdef
- /* BID is now saved in the smtp server ! - WG7J */
- time(&now);
- if(m->tomsgid != NULLCHAR && (fp = fopen(Historyfile,APPEND_TEXT)) != NULLFILE) {
- fprintf(fp,"%s %ld\n",m->tomsgid,now); /* Save BID in history file */
- fclose(fp);
- }
- #endif
- pwait (NULL); /* just to be nice to others */
- }
- if (m->sid & MBX_SID) {
- m->mysize = ((m->mysize + 1) % 10);
- if (!m->mysize)
- smtptick(NULL); /* wake SMTP to send that mail */
- } else {
- char buf[50], *cp;
- sprintf (buf, "%s", Hostname);
- if((cp = strchr(buf,'.')) != NULLCHAR)
- *cp = '\0';
- strupr(buf);
- tprintf ("\n*** Message forwarding to: %s\n*** MID: ", m->to);
- if (m->tomsgid)
- tprintf (m->tomsgid);
- else
- tprintf ("%ld_%s", lastsentid, buf);
- tprintf (" Size: %ld\n\n", messagesize);
- /* Instead of kicking off the smtp now, let it happen in a short time.
- * That way the user gets the prompt back immediately, and the smtp kick
- * will run when the user most likely is working on typing the next command.
- * this *should* improve the user's perception of system's speed, and
- * might speed up bbs forwarding a bit too... :-) - WG7J
- */
- {
- #define WAITTM 5000L
- extern struct timer Smtpcli_t;
- long t;
- int32 old;
-
- stop_timer(&Smtpcli_t);
- t = read_timer(&Smtpcli_t);
- old = Smtpcli_t.duration;
- if(t <= 0 || t > WAITTM)
- set_timer(&Smtpcli_t,WAITTM); /* set timer duration */
- if(Smtpcli_t.func == NULL) { /* in case not set yet */
- Smtpcli_t.func = (void (*)__ARGS((void*)))smtptick;/* what to call on timeout */
- Smtpcli_t.arg = NULL; /* dummy value */
- }
- start_timer(&Smtpcli_t); /* and fire it up */
- Smtpcli_t.duration = old;
- }
- #ifdef nope
- smtptick(NULL); /* wake SMTP to send that mail */
- #endif
- }
- pwait (NULL);
- return 0;
- }
-
- #ifdef NETROM
- static int
- dombnrnodes(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
-
- m = (struct mbx *)p;
-
- if(argc < 2)
- return doroutedump();
- if(*argv[1] == '*')
- argc = 1;
- return dorouteinfo(argc,argv,p);
- }
- #endif
-
- static int
- dosid(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
- char *cp, *flags;
- struct usock *up;
-
- m = (struct mbx *)p;
- if(argc == 1)
- return 1;
- if(argv[1][strlen(argv[1]) - 1] != ']') /* must be an SID */
- return 1;
- m->usecolor = 0;
- #ifdef notdef
- if(m->stype == 'Z' && strnicmp(argv[1],"cz",2) == 0) {
- /* LAN-LINK's [ZCZ] */
- m->sid |= MBX_LL;
- return 0;
- }
- #endif
- /* Other bbs's */
- m->sid = MBX_SID;
-
- /* Now check to see if this is an RLI board.
- * As usual, Hank does it a bit differently from
- * the rest of the world.
- */
- if(m->stype == 'R' && strnicmp(argv[1],"li",2) == 0)/* [RLI] at a minimum */
- m->sid |= MBX_RLI_SID;
- /* Check to see if the BBS supports a kludge called "hierarchical
- * routing designators."
- *
- * No need to check for ']' -- it must be there or this is not
- * a valid mbox id -- it is checked earlier (fix de OH3LKU)
- *
- * Sid format is [BBSTYPE-VERSION-OPTIONS]
- * check for LAST -, to allow for version portion. - WG7J
- */
- flags = strrchr(argv[1], '-');
- if(flags != NULLCHAR && (cp=strchr(flags+1,'h')) != NULLCHAR && strchr(cp+1,'$'))
- m->sid |= MBX_HIER_SID;
- #ifdef LZW
- /* Check to see if it's another TNOS board */
- if (flags != NULLCHAR && (cp=strchr(flags+1, 't')) != NULLCHAR) {
- if (m->state != MBX_FORWARD) { /* if forwarding, wait till we can send out SSID */
- up = itop(m->user);
- if(up->zout == NULLLZW)
- togglelzw (m->user, 1);
- }
- m->sid |= MBX_TNOS;
- }
- #endif
- if (flags != NULLCHAR && (cp=strchr (flags+1, 'm')) != NULLCHAR)
- m->sid |= MBX_MID;
- if (flags != NULLCHAR && (cp=strchr (flags+1, 'f')) != NULLCHAR) {
- m->sid |= MBX_FBB;
- if ((cp = strchr (flags+1, 'b')) != NULLCHAR)
- m->sid |= MBX_FBBCOMP;
- }
- m->mysize = 0;
- return 0;
- }
-
-
- int
- dombescape(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
-
- m = (struct mbx *)p;
- if(argc < 2) {
- tprintf("Escape is %s, Escape char: ", (m->privs & NO_ESCAPE) ? "OFF" : "ON");
- if(m->escape < 32)
- tprintf("CTRL-%c\n",m->escape+'A'-1);
- else
- tprintf("'%c'\n",m->escape);
- return 0;
- }
- if(strlen(argv[1]) > 1) {
- if(isdigit(*argv[1]))
- m->escape = (char) atoi(argv[1]);
- else {
- if( !strnicmp(argv[1],"OFF",3) || !strnicmp(argv[1],"dis",3) )
- m->privs |= NO_ESCAPE;
- else
- m->privs &= ~NO_ESCAPE;
- }
- } else
- m->escape = *argv[1];
- return 0;
- }
-
- /* Routine for finding out total number of messages for an area and the
- number of messages that are new to this user. Just reports NEW messages,
- does not check their read status (for personal areas). Though it USES the
- mbox structure, it returns it back to the previous state. This routine
- reads the area.ctl files, which just contain a bid for each message. */
-
- static void
- statarea(m, area, total, new, hold, special)
- register struct mbx *m;
- char *area;
- int *total, *new, *hold, special;
- {
- long last, newlast, num;
- char oldarea[20], buf[256];
- FILE *fp;
- long size;
- struct let *lt;
- register struct let *cmsg;
- register int i;
- register int tnew, ttotal, thold;
-
- ttotal = tnew = thold = 0;
- #ifdef USERLOG
- last = m->lastread;
- newlast = m->newlastread;
- m->lastread = 0;
- strcpy (oldarea, m->area);
- strcpy (m->area, area);
- if (!lockit (m)) {
- /* only read last read message-id if this is not a bbs,
- * current area is a public area and not 'help'
- * or area starts with 'sys'
- * read in all cases if a SYSOP
- */
-
- if(!(m->sid & MBX_SID))
- if( (stricmp(area,"help") && isarea(area)) || !strnicmp(m->area,"sys",3) || (m->privs & SYSOP_CMD))
- getlastread(m);
- pwait (NULL);
- sprintf (buf, "%s/CONTROL/%s", Mailspool, m->area);
- nntp_name_expansion (buf);
- strcat (buf, ".ctl");
- if ((fp = subdir_fopen (buf, READ_BINARY)) != NULLFILE) {
- size = filelength (fileno(fp));
- lt = (struct let *) malloc (size);
- fread (lt, size, 1, fp);
- fclose(fp);
- ttotal = (int) (size / (long) sizeof(struct let));
- pwait(NULL);
- for (cmsg = lt,i = 0; i < ttotal; i++, cmsg++)
- if (!special) {
- if ((cmsg->bid > m->lastread) && !(cmsg->status & BM_DELETE))
- tnew += 1;
- if (cmsg->status & BM_ONHOLD)
- thold += 1;
- } else {
- if (!(cmsg->status & BM_READ))
- tnew += 1;
- }
- free (lt);
- }
- pwait (NULL);
- m->lastread = last;
- m->newlastread = newlast;
- rmlock (Mailspool, m->area);
- strcpy (m->area, oldarea);
- }
- #endif
- *new = tnew;
- *total = ttotal;
- *hold = thold;
- }
-
-
- static int
- doarea(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
- char *cp, *area, *tmparea, *theone;
- FILE *fp;
- char buf[MBXLINE];
- int k;
- int hold, total, new, xtotal = 0, xnew = 0;
- struct no_mf *nm;
- struct ffblk ff;
-
- m = (struct mbx *) p;
- if ((m->stype == 'F') && m->usecolor && !access (ANSIArea, 0)) {
- colorfile (ANSIArea, m->colorset);
- return 0;
- }
- if(argc < 2 || m->stype == 'N' || m->stype == 'S') {
- area = strdup(m->area);
- tmparea = strdup(m->area);
- while((cp = strchr(tmparea,'/')) != NULLCHAR)
- *cp = '.';
- bbscolorcls (m);
- tprintf("Current message area is: %s\n\n",tmparea);
- free (tmparea);
-
- bbscolorchange (m, "0B");
- tputs("Available areas are:\n");
- total = m->nmsgs;
- new = m->newmsgs;
- if (stricmp (m->area, m->name)) {
- changearea(m,m->name, (int) 1);
- }
- else
- scanmail (m);
- if ((m->stype == 'N' && m->newmsgs) || m->stype != 'N') {
- bbscolorchange (m, "09");
- tprintf ("%-15s ",m->name);
- }
- if(m->stype == 'F')
- tputs(" Your private mail area\n");
- else if ((m->stype == 'S') || (m->stype == 'N' && m->newmsgs)) {
- bbscolorchange (m, "07");
- tprintf(MessageData, m->nmsgs,
- m->nmsgs == 1 ? " " : "s", m->newmsgs);
- /* tprintf(MessageData, total,total == 1 ? " " : "s", new); */
- xtotal += total;
- xnew += new;
- }
- else if (m->stype != 'N')
- tputc('\n');
- theone = Arealist;
- if((m->privs & SYSOP_CMD) && (!access(AreaSlist, 0)))
- theone = AreaSlist;
- if((fp = fopen(theone,READ_TEXT)) == NULLFILE)
- return 0;
- if(m->stype == 'F') {
- sendfile(fp,m->user,ASCII_TYPE,0);
- tputc('\n');
- }
- else if (m->stype == 'S' || m->stype == 'N') {
- while(fgets(buf,MBXLINE,fp) != NULLCHAR) {
- pwait(NULL);
- if(isalnum(buf[0])) { /* skip comments */
- if((cp=strpbrk(buf," \t")) != NULLCHAR)
- *cp = '\0';
- statarea (m, buf, &total, &new, &hold, 0);
- if (m->stype == 'S' || new) {
- bbscolorchange (m, "09");
- tprintf ("%-15.15s ", buf);
- bbscolorchange (m, "07");
- if ((m->privs & SYSOP_CMD) && hold)
- tprintf(SMessageData, total,
- total == 1 ? " " : "s", new, hold);
- else
- tprintf(MessageData, total,
- total == 1 ? " " : "s", new);
- usflush(Curproc->output);
- xtotal += total;
- xnew += new;
- }
- }
- }
- if ((m->privs & SYSOP_CMD) && argv[1][0] == 'a') { /* also list mailfor's if 'AN|S all' */
- sprintf(buf,"%s/*.txt",Mailspool);
- if (findfirst(buf, &ff, 0) == 0) {
- do {
- pwait(NULL); /* Let others run */
- *(strchr(ff.ff_name,'.')) = '\0';
- /*must be private mail area, and not on exclude list !*/
- if(!issysarea(ff.ff_name)) {
- if (!stricmp (ff.ff_name, m->name))
- continue;
- statarea (m, ff.ff_name, &total, &new, &hold, 1);
- if (m->stype == 'S' || new) {
- bbscolorchange (m, "09");
- tprintf ("%-15.15s ", ff.ff_name);
- bbscolorchange (m, "07");
- tprintf(MessageData, total,
- total == 1 ? " " : "s", new);
- usflush(Curproc->output);
- xtotal += total;
- xnew += new;
- }
- }
- } while (findnext(&ff) == 0);
- }
- }
- bbscolorchange (m, "0B");
- tputs("*** Total *** ");
- tprintf(MessageData, xtotal,xtotal == 1 ? " " : "s", xnew);
- usflush(Curproc->output);
- tputc('\n');
- }
- else {
- /* send only the area names, not the description */
- k = 0;
- while(fgets(buf,MBXLINE,fp) != NULLCHAR) {
- if(isalnum(buf[0])) { /* skip comments */
- if((cp=strpbrk(buf," \t")) != NULLCHAR)
- *cp = '\0';
- tprintf ("%-15.15s", buf);
- if (++k == 5) {
- tputc('\n');
- k = 0;
- }
- }
- }
- if (k)
- tputc('\n');
- bbscolorchange (m, "0A");
- tputs("\nType AF to get description of areas\n\n");
- }
- if (stricmp (area, m->area))
- changearea(m,area, (int) 0);
- free(area);
- fclose(fp);
- return 0;
- }
- if((m->privs & SYSOP_CMD) || stricmp(m->name,argv[1]) == 0){
- /*Private mail-areas*/
- changearea(m,argv[1], (int) 1);
- if(m->nmsgs && !(m->privs&IS_BBS)){
- if(!stricmp(m->name,m->area))
- tputs("You have ");
- else {
- area = strdup(m->area);
- while((cp = strchr(area,'/')) != NULLCHAR)
- *cp = '.';
- tprintf("%s: ",area);
- free(area);
- }
- tprintf((m->hmsgs) ? SMessageData : MessageData, m->nmsgs,
- m->nmsgs == 1 ? " " : "s", m->newmsgs, m->hmsgs);
- }
- if (m->stype == 'L') {
- m->stype = ' ';
- dolistnotes (0, 0, m);
- }
- return 0;
- }
- if(isarea(argv[1])) {
- /*Public mail areas*/
- changearea(m,argv[1], (int) 1);
- area = strdup(m->area);
- while((cp = strchr(area,'/')) != NULLCHAR)
- *cp = '.';
- if (!(m->privs & IS_BBS))
- #ifdef USERLOG
- tprintf("%s: %d message%s - %d new\n",area,m->nmsgs,
- m->nmsgs == 1 ? " " : "s ", m->newmsgs);
- #else
- tprintf("%s: %d message%s.\n", area, m->nmsgs,
- m->nmsgs == 1 ? "" : "s");
- #endif
- free(area);
- if (m->stype == 'L') {
- m->stype = ' ';
- dolistnotes (0, 0, m);
- }
- }
- else
- tprintf("No such message area: %s\n",argv[1]);
- return 0;
- }
-
- char *
- nntp_name_expansion (name)
- char *name;
- {
- char *cp;
-
- while((cp = strpbrk(name,".\\")) != NULLCHAR)
- *cp = '/';
- return name;
- }
-
-
- /* subroutine to do the actual switch from one area to another */
- /* USERLOGGING added by WG7J */
- void
- changearea(m,area,setit)
- struct mbx *m;
- char *area;
- int setit;
- {
- char *cp;
-
- #ifdef USERLOG
- if (setit)
- setlastread(m);
- #endif
- closenotes(m);
- m->nmsgs = m->newmsgs = m->current = 0;
- strcpy(m->area,area);
- nntp_name_expansion (m->area);
-
- #ifdef USERLOG
- /* only read last read message-id if this is not a bbs,
- * current area is a public area and not 'help'
- * or area starts with 'sys'
- * read in all cases if a SYSOP
- */
- if(!(m->sid & MBX_SID))
- if( (stricmp(area,"help") && isarea(area)) || !strnicmp(m->area,"sys",3) || (m->privs & SYSOP_CMD))
- getlastread(m);
- #endif
- scanmail(m);
- }
-
- /* Generic mbox gateway code. It sends and frees the contents of m->startmsg
- * when the connection has been established unless it a null pointer.
- */
- int
- gw_connect(m,s,fsocket,len)
- struct mbx *m;
- int s;
- struct sockaddr *fsocket;
- int len;
- {
- int c;
- char *cp, *cp1;
- struct proc *child;
- struct gwalarm *gwa;
- char *node, *tocall, whereto[128], buf[80];
- char temp[AXBUF];
- struct nrroute_tab *rp;
-
- sockmode(s,SOCK_ASCII);
- child = newproc("gw supervisor",256,gw_superv,0,Curproc,m,0);
- tputs("Trying...");
- if(m->privs & NO_ESCAPE)
- tputc('\n');
- else {
- tputs(" The escape character is: ");
- if(m->escape < 32)
- tprintf("CTRL-%c\n",m->escape+'A'-1);
- else
- tprintf("'%c'\n",m->escape);
- }
- usflush(Curproc->output);
-
- /*find out where we're going to*/
- tocall = strdup(psocket(fsocket));
- if((cp1 = strchr(tocall,' ')) != NULLCHAR)
- *cp1 = '\0';
- #ifdef NETROM
- if(fsocket->sa_family == AF_NETROM) {
- /*find the node alias*/
- setcall(temp,tocall);
- rp = find_nrroute(temp);
- node = strdup(rp->alias);
- if((cp1 = strchr(node,' ')) != NULLCHAR)
- *cp1 = '\0';
- sprintf(whereto,"%s:%s",node,tocall);
- free(node);
- } else
- #endif
- strcpy(whereto,tocall);
- free(tocall);
-
- if(connect(s,(char *)fsocket,len) == -1){
- if((cp = sockerr(s)) != NULLCHAR) {
- switch(cp[0]) {
- case 'R':
- sprintf(buf,"%susy from",
- (m->family == AF_NETROM)?"B":"*** b");
- break;
- case 'T':
- if(m->family != AF_NETROM) {
- sprintf(buf,"*** timeout with");
- break;
- }
- default:
- sprintf(buf,"%sailure with",
- (m->family == AF_NETROM)?"F":"*** f");
- break;
- }
- tprintf("%s%s %s\n\n",
- (m->family == AF_NETROM) ? Mbnrid : "",buf,whereto);
- }
- shutdown(s,2); /* HB9RWM suggestion */
- close_s(s);
- killproc(child);
- /* Free m->starmsg if set ! - WG7J */
- if(m->startmsg != NULLCHAR) {
- free(m->startmsg);
- m->startmsg = NULLCHAR;
- }
-
- return 0;
- }
- /* The user did not type the escape character */
- killproc(child);
-
- tprintf("%s%sonnected to %s\n",
- (m->family == AF_NETROM) ? Mbnrid : "",
- (m->family == AF_NETROM) ? "C" : "*** c",
- whereto);
-
- if(m->startmsg != NULLCHAR){
- usputs(s,m->startmsg);
- free(m->startmsg);
- m->startmsg = NULLCHAR;
- }
-
- /* Since NOS does not flush the output socket after a certain
- * period of time, we have to arrange that ourselves.
- */
- gwa = (struct gwalarm *) mallocw(sizeof(struct gwalarm));
- gwa->s1 = Curproc->output;
- gwa->s2 = s;
- set_timer(&gwa->t,2*1000L);
- gwa->t.func = gw_alarm;
- gwa->t.arg = (void *) gwa;
- start_timer(&gwa->t);
- /* Fork off the receive process */
- child = newproc("gw in",1024,gw_input,s,m,Curproc,0);
-
- for(;;){
- if((c = recvchar(Curproc->input)) == EOF)
- break;
- /* Only check ESCAPE char if that is currently turned on */
- if( !(m->privs & NO_ESCAPE) && c == m->escape){
- if(socklen(Curproc->input,0))
- recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
- break;
- }
- #ifdef MBXTDISC
- if(c == '\n')
- start_timer(&m->tdisc);
- #endif
- if(usputc(s,c) == EOF)
- break;
- }
- stop_timer(&gwa->t);
- free((char *)gwa);
- close_s(s);
- killproc(child); /* get rid of the receive process */
- if(m->family == AF_INET)
- tprintf("%c%c%c\n",IAC,WONT,TN_ECHO);
- return 0;
- }
-
- static void
- gw_input(s,notused,p)
- int s;
- void *notused;
- void *p;
- {
- int c;
- struct proc *parent;
- struct mbx *m;
- char *cp, *cp1;
- char response[4];
-
- parent = (struct proc *) p;
- m = (struct mbx *) notused;
-
- cp1 = strdup(Mbnrid);
- if((cp = strchr(cp1,'}')) != NULLCHAR)
- *cp = '\0';
- strupr(cp1);
-
- #ifdef notdef
- while((c = recvchar(s)) != EOF)
- tputc(c);
- #endif
- while((c = recvchar(s)) != EOF){
- if(c != IAC){
- tputc((char)c);
- continue;
- }
- /* IAC received, get command sequence */
- c = recvchar(s);
- switch(c){
- case WILL:
- response[0] = IAC;
- response[1] = DONT;
- response[2] = recvchar(s);
- response[3] = '\0';
- usputs(s,response);
- break;
- case WONT:
- case DONT:
- c = recvchar(s);
- break;
- case DO:
- response[0] = IAC;
- response[1] = WONT;
- response[2] = recvchar(s);
- response[3] = '\0';
- usputs(s,response);
- break;
- case IAC: /* Escaped IAC */
- usputc(s,IAC);
- break;
- }
- }
-
- if((cp = sockerr(s)) != NULLCHAR && m->family != AF_NETROM) {
- switch(cp[0]) {
- case 'T':
- usprintf(m->user,"\n*** %s: Link failure",cp1);
- break;
- case 'R':
- usprintf(m->user,"*** DM received");
- break;
- }
- }
- usprintf(m->user,"\n%s%seconnected to %s\n\n",
- (m->family == AF_NETROM) ? Mbnrid : "",
- (m->family == AF_NETROM) ? "R" : "*** r",
- cp1);
-
- free(cp1);
- cp1 = NULLCHAR;
-
- /* Tell the parent that we are no longer connected */
- alert(parent,ENOTCONN);
- pwait(Curproc); /* Now wait to be killed */
- }
-
- /* Check if the escape character is typed while the parent process is busy
- * doing other things.
- */
- static void
- gw_superv(null,proc,p)
- int null;
- void *proc;
- void *p;
- {
- struct proc *parent;
- struct mbx *m;
- int c;
-
- parent = (struct proc *) proc;
- m = (struct mbx *) p;
- while((c = recvchar(Curproc->input)) != EOF)
- if(c == m->escape){
- /* flush anything in the input queue */
- if(socklen(Curproc->input,0))
- recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
- break;
- }
- alert(parent,EINTR); /* Tell the parent to quit */
- pwait(Curproc); /* Please kill me */
- }
-
- static void
- gw_alarm(p)
- void *p;
- {
- struct gwalarm *gwa = (struct gwalarm *)p;
- char oldbl;
- struct usock *up;
-
- /* Flush sockets s1 and s2, but first make sure that the socket
- * is set to non-blocking mode, to prevent the flush from blocking
- * if the high water mark has been reached.
- */
- if((up = itop(gwa->s1)) != NULLUSOCK) {
- oldbl = up->noblock;
- up->noblock = 1;
- usflush(gwa->s1);
- up->noblock = oldbl;
- }
- if((up = itop(gwa->s2)) != NULLUSOCK) {
- oldbl = up->noblock;
- up->noblock = 1;
- usflush(gwa->s2);
- up->noblock = oldbl;
- }
- start_timer(&gwa->t);
- }
-
- /* States for send line parser state machine */
- #define LOOK_FOR_USER 2
- #define IN_USER 3
- #define AFTER_USER 4
- #define LOOK_FOR_HOST 5
- #define IN_HOST 6
- #define AFTER_HOST 7
- #define LOOK_FOR_FROM 8
- #define IN_FROM 9
- #define AFTER_FROM 10
- #define LOOK_FOR_MSGID 11
- #define IN_MSGID 12
- #define FINAL_STATE 13
- #define ERROR_STATE 14
-
- /* Prepare the addressee. If the address is bad, return -1, otherwise
- * return 0
- */
- static int
- mbx_to(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register char *cp;
- register struct mbx *m;
- register int state, i;
- char *user, *host, *from, *msgid;
- int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0;
-
- m = (struct mbx *)p;
- /* Free anything that might be allocated
- * since the last call to mbx_to() or mbx_reply()
- */
- free(m->to);
- m->to = NULLCHAR;
- free(m->tofrom);
- m->tofrom = NULLCHAR;
- free(m->tomsgid);
- m->tomsgid = NULLCHAR;
- free(m->origto);
- m->origto = NULLCHAR;
- free(m->origbbs);
- m->origbbs = NULLCHAR;
- free(m->subject);
- m->subject = NULLCHAR;
- free(m->date);
- m->date = NULLCHAR;
-
- if(argc == 1)
- return -1;
- i = 1;
- cp = argv[i];
- state = LOOK_FOR_USER;
- while(state < FINAL_STATE){
- #ifdef MBDEBUG
- tprintf("State is %d, char is %c\n", state, *cp);
- #endif
- switch(state){
- case LOOK_FOR_USER:
- if(*cp == '@' || *cp == '<' || *cp == '$'){
- state = ERROR_STATE; /* no user */
- } else {
- user = cp; /* point at start */
- userlen++; /* start counting */
- state = IN_USER;
- }
- break;
- case IN_USER:
- switch(*cp){
- case '\0':
- state = AFTER_USER; /* done with username */
- break;
- case '@':
- state = LOOK_FOR_HOST; /* hostname should follow */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* from name should follow */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id should follow */
- break;
- default:
- userlen++; /* part of username */
- }
- break;
- case AFTER_USER:
- switch(*cp){
- case '@':
- state = LOOK_FOR_HOST; /* hostname follows */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* fromname follows */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- state = ERROR_STATE;
- }
- break;
- case LOOK_FOR_HOST:
- if(*cp == '@' || *cp == '<' || *cp == '$'){
- state = ERROR_STATE;
- break;
- }
- if(*cp == '\0')
- break;
- host = cp;
- hostlen++;
- state = IN_HOST;
- break;
- case IN_HOST:
- switch(*cp){
- case '\0':
- state = AFTER_HOST; /* found user@host */
- break;
- case '@':
- state = ERROR_STATE; /* user@host@? */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* fromname follows */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- hostlen++;
- }
- break;
- case AFTER_HOST:
- switch(*cp){
- case '@':
- state = ERROR_STATE; /* user@host @ */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* user@host < */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* user@host $ */
- break;
- default:
- state = ERROR_STATE; /* user@host foo */
- }
- break;
- case LOOK_FOR_FROM:
- if(*cp == '@' || *cp == '<' || *cp == '$'){
- state = ERROR_STATE;
- break;
- }
- if(*cp == '\0')
- break;
- from = cp;
- fromlen++;
- state = IN_FROM;
- break;
- case IN_FROM:
- switch(*cp){
- case '\0':
- state = AFTER_FROM; /* user@host <foo */
- break;
- case '<':
- state = ERROR_STATE; /* user@host <foo< */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- fromlen++;
- }
- break;
- case AFTER_FROM:
- switch(*cp){
- case '@': /* user@host <foo @ */
- case '<': /* user@host <foo < */
- state = ERROR_STATE;
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* user@host <foo $ */
- break;
- default:
- state = ERROR_STATE; /* user@host foo */
- }
- break;
- case LOOK_FOR_MSGID:
- if(*cp == '\0')
- break;
- msgid = cp;
- msgidlen++;
- state = IN_MSGID;
- break;
- case IN_MSGID:
- if(*cp == '\0')
- state = FINAL_STATE;
- else
- msgidlen++;
- break;
- default:
- /* what are we doing in this state? */
- state = ERROR_STATE;
- }
- if(*(cp) == '\0'){
- ++i;
- if(i < argc)
- cp = argv[i];
- else break;
- } else
- ++cp;
- }
- if(state == ERROR_STATE || state == LOOK_FOR_HOST
- || state == LOOK_FOR_FROM || state == LOOK_FOR_MSGID)
- return -1; /* syntax error */
-
- m->to = mallocw(userlen + hostlen + 2);
-
- strncpy(m->to, user, userlen);
- m->to[userlen] = '\0';
-
- if(hostlen){
- m->to[userlen] = '@';
- strncpy(m->to + userlen + 1, host, hostlen);
- m->to[userlen + hostlen + 1] = '\0';
- }
- if(fromlen){
- m->tofrom = mallocw(fromlen + 1);
- strncpy(m->tofrom, from, fromlen);
- m->tofrom[fromlen] = '\0';
- }
- if(msgidlen){
- m->tomsgid = mallocw(msgidlen + 1);
- strncpy(m->tomsgid, msgid, msgidlen);
- m->tomsgid[msgidlen] = '\0';
- }
- return 0;
- }
-
- /* This opens the data file and writes the mail header into it.
- * Returns 0 if OK, and -1 if not.
- */
- int
- mbx_data(m,cclist,extra, returnreceipt)
- struct mbx *m;
- struct list *cclist; /* list of carbon copy recipients */
- char *extra; /* optional extra header lines */
- int returnreceipt;
- {
- time_t t;
- struct list *ap;
- int cccnt = 0;
- char buf[80];
- char stype, *cp = NULLCHAR;
-
- #ifdef notdef
- time(&t);
- /*These 2 lines get added again when the smtp-server handles the mail
- *not really needed - WG7J
- */
- fprintf(m->tfile,Hdrs[RECEIVED]);
- if(m->tofrom != NULLCHAR)
- fprintf(m->tfile,"from %s ",m->name);
- fprintf(m->tfile,"by %s (%s)\n\tid AA%ld ; %s",
- Hostname, Version, get_msgid(0),ptime(&t));
- #endif
-
- #ifdef nope
- if(!isspace(m->stype) && ((m->stype != 'R' && m->stype != 'F') ||
- (m->sid & MBX_SID) !=0))
- fprintf(m->tfile,"%s%c\n", Hdrs[BBSTYPE],m->stype);
- #else
- stype = m->stype;
- if(isspace(stype) || stype == 'R' || stype == 'F')
- stype = 'P';
- fprintf(m->tfile,"%s%c\n", Hdrs[BBSTYPE],stype);
- #endif
-
- /* If m->date is set, use this one (comes from bbs-forwarded mail) */
- if(m->date != NULLCHAR)
- fprintf(m->tfile,"%s%s",Hdrs[DATE],m->date);
- else {
- time(&t);
- fprintf(m->tfile,"%s%s",Hdrs[DATE],ptime(&t));
- }
-
- /* Bulletin ID, if any */
- fprintf(m->tfile,Hdrs[MSGID]);
- if(m->tomsgid)
- fprintf(m->tfile,"<%s@%s.bbs>\n", m->tomsgid, m->name);
- else {
- lastsentid = get_msgid(1);
- fprintf(m->tfile,"<%ld@%s>\n",lastsentid, Hostname);
- }
-
- /* From : , could use 'real bbs address', if origbbs is set */
- fprintf(m->tfile,Hdrs[FROM]);
- if(m->tofrom) { /* BBS style '< call' */
- if(m->origbbs != NULLCHAR)
- sprintf(buf,"%s@%s\n",m->tofrom,m->origbbs);
- else
- sprintf(buf,"%s%%%s@%s\n",m->tofrom, m->name, Hostname);
- } else {
- if(m->origbbs != NULLCHAR)
- sprintf(buf,"%s@%s\n",m->name,m->origbbs);
- else
- sprintf(buf,"%s@%s ",m->name,Hostname);
- }
-
- #ifdef WPAGES
- if(m->origbbs != NULLCHAR)
- wpageAdd (buf, 0, 1); /* update users file */
- #endif
- if (!m->tofrom && m->origbbs == NULLCHAR) {
- if (strcmp(m->realname, "()")) {
- strcat (buf, m->realname);
- }
- strcat (buf, "\n");
- }
- fputs (buf, m->tfile);
- if ((m->origto != NULLCHAR) && ((cp = strchr (m->origto, '(')) != 0))
- *(cp-1) = 0;
- fprintf(m->tfile,"%s%s\n",Hdrs[TO],m->origto != NULLCHAR ? m->origto : m->to);
- if (cp)
- *(cp-1) = ' ';
-
- if (m->change != -1) {
- /* Write Cc: line */
- for(ap = cclist; ap != NULLLIST; ap = ap->next) {
- if(cccnt == 0){
- fprintf(m->tfile,"%s",Hdrs[CC]);
- cccnt = 4;
- }
- else {
- fprintf(m->tfile,", ");
- cccnt += 2;
- }
- if(cccnt + strlen(ap->val) > 80 - 3) {
- fprintf(m->tfile,"\n ");
- cccnt = 4;
- }
- fputs(ap->val,m->tfile);
- cccnt += strlen(ap->val);
- }
- if(cccnt)
- fputc('\n',m->tfile);
- }
- fprintf(m->tfile,"%s%s\n",Hdrs[SUBJECT],m->subject);
-
- #ifdef notdef
- /*not really needed, the 'From <user%fwdbbs@host>' shows this too!*/
- /* Also store the 'real smtp from' address */
- if((m->tofrom != NULLCHAR) && (m->origbbs != NULLCHAR))
- fprintf(m->tfile,"%s%s%%%s@%s\n",Hdrs[XFROM],m->tofrom,m->name, Hostname);
- #endif
-
- if(extra != NULLCHAR)
- fprintf(m->tfile,extra);
-
- /*Finish smtp headers*/
- fprintf(m->tfile,"\n");
- if(Smtpheaders && m->origbbs == NULLCHAR) { /* RFC headers in data area */
- char *cp;
-
- fprintf(m->tfile,Hdrs[MSGID]);
- if(m->tomsgid)
- fprintf(m->tfile,"%s\n", m->tomsgid);
- else {
- strcpy (buf, Hostname);
- if((cp = strchr(buf,'.')) != NULLCHAR)
- *cp = '\0';
- fprintf(m->tfile,"%ld_%s\n",lastsentid, buf);
- }
-
- /* Add a return receipt line, if requested */
- if (returnreceipt) {
- pax25(buf,Mycall);
- if((cp = strchr(buf,'-')) != NULLCHAR)
- *cp = '\0'; /* remove SSID */
- strlwr (buf);
- fprintf(m->tfile, "%s%s@%s", Hdrs[RRECEIPT],m->name,buf);
-
- sprintf(buf,"%s%s ", (Mbhaddress != NULLCHAR) ? "." : "",
- (Mbhaddress != NULLCHAR) ? Mbhaddress : "");
- strlwr (buf);
- if (strcmp(m->realname, "()"))
- strcat (buf, m->realname);
- strcat (buf, "\n");
- fputs (buf, m->tfile);
- }
-
- if (isgroup (m->to))
- fprintf (m->tfile, "%s%s@%s\n", Hdrs[XMAILGROUP], m->to, Hostname);
-
- pax25(buf,Mycall);
- if((cp = strchr(buf,'-')) != NULLCHAR)
- *cp = '\0'; /* remove SSID */
- strlwr (buf);
- fprintf(m->tfile,"%s%s@%s", Hdrs[FROM], m->name, buf);
-
- sprintf(buf,"%s%s ", (Mbhaddress != NULLCHAR) ? "." : "",
- (Mbhaddress != NULLCHAR) ? Mbhaddress : "");
- strlwr (buf);
- if (strcmp(m->realname, "()"))
- strcat (buf, m->realname);
- strcat (buf, "\n");
- fputs (buf, m->tfile);
-
- cp = (m->origto != NULLCHAR) ? m->origto : m->to;
- fprintf(m->tfile,"%s%s",Hdrs[TO],cp);
- if ((cp = mblookname (NULLMBX, cp)) != 0) {
- fputs (cp, m->tfile);
- free (cp);
- }
- fputs("\n\n", m->tfile);
- }
- return 0;
- }
-
-
- /* Attempt to determine if this is third-party mail. */
- static int
- thirdparty(m)
- struct mbx *m;
- {
- char buf[MBXLINE], *cp, *rp;
- FILE *fp;
-
- if(strpbrk(m->to,"@%!") != NULLCHAR)
- return 0;
-
- rp = strdup(Hostname);
-
- if((cp = strchr(rp, '.')) != NULLCHAR)
- *cp = '\0';
-
- if(stricmp(m->to,rp) == 0){
- free(rp);
- return -1;
- }
- free(rp);
-
- if(stricmp(m->to,"sysop") == 0)
- return -1;
-
- if((fp = fopen(Arealist,READ_TEXT)) == NULLFILE)
- return 0;
-
- while(fgets(buf,MBXLINE,fp) != NULLCHAR){
- /* The first word on each line is all that matters */
- if((cp = strpbrk(buf, " \t")) != NULLCHAR)
- *cp = '\0';
- if(stricmp(m->to,buf) == 0){
- fclose(fp);
- return -1;
- }
- }
- fclose(fp);
- return 0;
- }
-
- #ifdef NETROM
- extern struct nrroute_tab *find_nrboth __ARGS((char *alias,char *call));
- #endif
-
- static int
- dombconnect(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
- struct nrroute_tab *np;
- int ndigis,i,s;
- struct sockaddr_nr lsocket,fsocket;
- struct sockaddr_ax alsocket; /*the local socket*/
- struct sockaddr_ax afsocket; /*the remote socket*/
- struct iface *ifp;
- char alias[AXBUF];
- char local_call[AXALEN];
- char digis[MAXDIGIS][AXALEN];
- char target[AXALEN];
- struct session *sp;
-
- m = (struct mbx *) p;
-
- if(argc == 1){
- #ifdef CONVERS
- if(!Mbconverse) {
- tputs("Conference server not enabled\n");
- return 0;
- }
- if(m->privs & NO_CONVERS) {
- tputs(Noperm);
- mail_error("%s: converse denied\n",m->name);
- return 0;
- }
- #ifdef GWTRACE
- log(m->user,"MBOX CONFERENCE: %s",m->name);
- #endif
- m->state = MBX_CONVERS;
- usflush(Curproc->output);
- if (Current->type == 1)
- tprintf ("%c%c", IAC, CLEARSCREEN); /* sets Current->split */
- sp = Current;
- pwait (NULL);
- mbox_converse(m->user, m->name, (int) -1, m);
- if (sp->split) {
- usflush(Curproc->output);
- tprintf ("%c%c", IAC, CLEARSPLIT); /* clears Current->split */
- usflush(Curproc->output);
- sp->split = 0;
- }
- #else
- dombconnecthelp();
- #endif
- return 0;
- }
-
- if(MBSecure)
- #ifdef NETROM
- if((m->family != AF_AX25) && (m->family != AF_NETROM)) {
- #else
- if(m->family != AF_AX25) {
- #endif
- tputs(Noperm);
- mail_error("%s: gateway denied (secure mode): %s\n",m->name,cmd_line(argc,argv,m->stype));
- return 0;
- }
-
- if (argc == 2) {
- #ifndef NETROM
- dombconnecthelp();
- return 0;
- }
- #else
- /*NETROM connection wanted*/
- if(!(m->privs & NETROM_CMD)) {
- tputs(Noperm);
- mail_error("%s: NETROM gate to %s denied\n",m->name,argv[1]);
- return 0;
- }
-
- if(Nr_iface == NULLIF){
- tputs("NET/ROM not activated.\n\n");
- return 0;
- }
- /* See if the requested destination is a known alias or call,
- * use it if it is. Otherwize give an error message.
- */
- putalias(alias,argv[1],0);
- strupr(argv[1]); /*make sure it's upper case*/
- if((np = find_nrboth(alias,argv[1])) == NULLNRRTAB){
- /*no such call or node alias*/
- tputs("no such node\n\n");
- dombconnecthelp();
- dombports(0,NULL,NULL);
- return 0;
- }
-
- if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
- tputs(Nosock);
- return 0;
- }
- #ifdef GWTRACE
- log(m->user,"MBOX NETROM: %s to %s",m->name,argv[1]);
- #endif
- lsocket.nr_family = AF_NETROM;
-
- /* Set up our local username, bind would use Mycall instead */
- memcpy(lsocket.nr_addr.user,m->call,AXALEN);
- /* Set up our source address */
- memcpy(lsocket.nr_addr.node,Nr_iface->hwaddr,AXALEN);
-
- bind(s,(char *)&lsocket,sizeof(struct sockaddr_nr));
-
- memcpy(fsocket.nr_addr.user,np->call,AXALEN);
- memcpy(fsocket.nr_addr.node,np->call,AXALEN);
- fsocket.nr_family = AF_NETROM;
- m->state = MBX_GATEWAY;
- return gw_connect(m,s,(struct sockaddr *)&fsocket, sizeof(struct sockaddr_nr));
- }
- #endif /*NETROM*/
-
- #ifdef AX25
- if(argc > 2) {
- /*AX25 gateway connection wanted*/
- if(!(m->privs & AX25_CMD)) {
- tputs(Noperm);
- mail_error("%s: AX.25 gate to %s on %s denied\n",m->name,argv[2],argv[1]);
- return 0;
- }
-
- if( ((ifp = if_lookup(argv[1])) == NULLIF) ||
- ((ifp->flags & HIDE_PORT) && !(m->privs & SYSOP_CMD)) ||
- (ifp->type != CL_AX25) ) {
- tprintf("Unknown port %s\n",argv[1]);
- dombports(0,NULL,NULL);
- return 0;
- }
- if(ifp->type != CL_AX25){
- tprintf("Port %s not usable for AX.25 connects\n",argv[1]);
- dombports(0,NULL,NULL);
- return 0;
- }
- if(setcall(target,argv[2]) == -1){
- tprintf("Bad call %s\n",argv[2]);
- return 0;
- }
- /* If digipeaters are given, put them in the routing table */
- if(argc > 3){
- ndigis = argc - 3;
- if(ndigis > MAXDIGIS){
- tputs("Too many digipeaters\n");
- return 0;
- }
- for(i=0;i<ndigis;i++){
- if(setcall(digis[i],argv[i+3]) == -1){
- tprintf("Bad digipeater %s\n",argv[i+3]);
- return 0;
- }
- }
- if(ax_add(target,AX_AUTO,digis,ndigis,ifp) == NULLAXR){
- tputs("AX25 route add failed\n");
- return 0;
- }
- }
- if((s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
- tputs(Nosock);
- return 0;
- }
- #ifdef GWTRACE
- log(m->user,"MBOX AX25: %s to %s on %s",m->name,argv[2],argv[1]);
- #endif
-
- /*fill in the known stuff*/
- alsocket.sax_family = afsocket.sax_family= AF_AX25;
-
- /*the remote call to connect to*/
- setcall(afsocket.ax25_addr,argv[2]);
-
- /*the outgoing interface*/
- strncpy(afsocket.iface,argv[1],ILEN);
-
- /*now set local user call, invert ssid*/
- memcpy(local_call,m->call,AXALEN);
- local_call[AXALEN-1] ^= 0x1e;
- memcpy(alsocket.ax25_addr,local_call,AXALEN);
- /*and bind it (otherwize Mycall will be used!)*/
- bind(s,(char *)&alsocket,sizeof(struct sockaddr_ax));
- m->state = MBX_GATEWAY;
- return gw_connect(m,s,(struct sockaddr *)&afsocket, sizeof(struct sockaddr_ax));
- }
- #endif /* AX25 */
-
- return 0;
- }
-
- #endif /* MAILBOX */
-
-